aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw')
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/.gitignore3
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Agent.h136
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Args.c2613
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Args.h97
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Atoms.c796
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Atoms.h73
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Binder.c185
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Binder.h35
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/BitmapUtils.c118
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Client.c546
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Client.h128
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.c1677
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Clipboard.h69
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Colormap.c600
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Colormap.h92
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Composite.c207
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Composite.h59
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Cursor.c600
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Cursor.h117
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Dialog.c546
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Dialog.h216
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Display.c2963
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Display.h178
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Drawable.c3308
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Drawable.h229
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Error.c644
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Error.h47
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Events.c4767
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Events.h238
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Extensions.c470
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Extensions.h43
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Font.c1864
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Font.h85
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GC.c1717
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCOps.c2104
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCOps.h113
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/GCs.h119
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Handlers.c1325
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Handlers.h129
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Holder.c235
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Holder.h35
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Icons.h39
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Image.c1828
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Image.h116
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Imakefile270
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Init.c581
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Init.h54
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keyboard.c1930
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keyboard.h135
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keystroke.c662
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Keystroke.h90
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Literals.h213
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Millis.c78
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Millis.h38
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdamage.c225
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c1362
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c1543
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXevents.c613
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXextension.c195
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglxext.c204
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyph.c381
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c180
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphRef.h60
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphSet.h64
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c743
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c123
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicture.c654
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXpicturestr_PictSolidFill.h63
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXproperty.c653
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXrender.c1730
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXresource.c595
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXshm.c547
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXwindow.c1127
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c245
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.c210
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Options.h479
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixels.c392
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixels.h188
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixmap.c1660
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h145
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pointer.c199
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Pointer.h62
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Reconnect.c849
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Reconnect.h78
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Render.c3047
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Render.h119
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Rootless.c1291
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Rootless.h101
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Screen.c4741
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Screen.h149
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Splash.c424
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Splash.h54
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Split.c1256
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Split.h92
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/TestExt.c91
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Trap.c122
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Trap.h124
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Utils.h55
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Visual.c167
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Visual.h81
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Window.c3930
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/Windows.h328
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xcomposite_nxagent.h106
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xfixes_nxagent.h90
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xinerama_nxagent.h74
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrandr_nxagent.h83
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrender_nxagent.h528
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrenderint_nxagent.h106
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/X11/include/xpm_nxagent.h259
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c50
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h45
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c120
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c349
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c50
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h45
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c4778
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h912
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile48
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c480
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h46
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c802
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h48
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Png.c730
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Png.h76
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c51
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c51
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h44
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Z.c309
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/compext/Z.h60
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/man/nxagent.11050
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm49
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm56
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/screensaver711
-rw-r--r--nx-X11/programs/Xserver/hw/nxagent/x2go.xpm163
137 files changed, 79802 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/nxagent/.gitignore b/nx-X11/programs/Xserver/hw/nxagent/.gitignore
new file mode 100644
index 000000000..256534b63
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/.gitignore
@@ -0,0 +1,3 @@
+miinitext.c
+stubs.c
+xpstubs.c
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Agent.h b/nx-X11/programs/Xserver/hw/nxagent/Agent.h
new file mode 100644
index 000000000..af8b62810
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Agent.h
@@ -0,0 +1,136 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright (c) 1995 X Consortium
+
+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, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+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 THE X CONSORTIUM 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.
+
+Except as contained in this notice, the name of the X Consortium shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the X Consortium.
+
+*/
+
+#ifndef __Agent_H__
+#define __Agent_H__
+
+/*
+ * Machines with a 64 bit library interface and a 32 bit
+ * server require name changes to protect the guilty.
+ */
+
+#ifdef _XSERVER64
+#define _XSERVER64_tmp
+#undef _XSERVER64
+typedef unsigned long XID64;
+typedef unsigned long Mask64;
+typedef unsigned long Atom64;
+typedef unsigned long VisualID64;
+typedef unsigned long Time64;
+#define XID XID64
+#define Mask Mask64
+#define Atom Atom64
+#define VisualID VisualID64
+#define Time Time64
+typedef XID Window64;
+typedef XID Drawable64;
+typedef XID Font64;
+typedef XID Pixmap64;
+typedef XID Cursor64;
+typedef XID Colormap64;
+typedef XID GContext64;
+typedef XID KeySym64;
+#define Window Window64
+#define Drawable Drawable64
+#define Font Font64
+#define Pixmap Pixmap64
+#define Cursor Cursor64
+#define Colormap Colormap64
+#define GContext GContext64
+#define KeySym KeySym64
+
+#define XlibAtom Atom64
+#define XlibWindow Window64
+#define XlibPixmap Pixmap64
+#define XlibFont Font64
+#define XlibKeySym KeySym64
+#define XlibXID XID64
+
+#else /*_XSERVER64*/
+
+#define XlibAtom Atom
+#define XlibWindow Window
+#define XlibPixmap Pixmap
+#define XlibFont Font
+#define XlibKeySym KeySym
+#define XlibXID XID
+
+#endif /*_XSERVER64*/
+
+#define NX_TRANS_SOCKET
+#define GC XlibGC
+#include <nx-X11/Xlib.h>
+#include <X11/extensions/shape.h>
+#undef GC
+
+#ifdef _XSERVER64_tmp
+#define _XSERVER64
+#undef _XSERVER64_tmp
+#undef XID
+#undef Mask
+#undef Atom
+#undef VisualID
+#undef Time
+#undef Window
+#undef Drawable
+#undef Font
+#undef Pixmap
+#undef Cursor
+#undef Colormap
+#undef GContext
+#undef KeySym
+#endif /*_XSERVER64_tmp*/
+
+#endif /* __Agent_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.c b/nx-X11/programs/Xserver/hw/nxagent/Args.c
new file mode 100644
index 000000000..5db7e0110
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Args.c
@@ -0,0 +1,2613 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef __sun
+#include <strings.h>
+#endif
+
+#include "X.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "globals.h"
+#include "scrnintstr.h"
+#include "dixstruct.h"
+#include "servermd.h"
+#include "opaque.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Args.h"
+#include "Options.h"
+#include "Binder.h"
+#include "Trap.h"
+#include "Screen.h"
+#include "Image.h"
+#ifdef RENDER
+#include "Render.h"
+#endif
+#include "Handlers.h"
+#include "Error.h"
+#include "Reconnect.h"
+#include "Utils.h"
+
+/*
+ * NX includes and definitions.
+ */
+
+#include "compext/Compext.h"
+#include <nx/NXpack.h>
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+
+#ifdef WATCH
+
+#include "unistd.h"
+
+#endif
+
+#ifdef PANORAMIX
+ #define PANORAMIX_DISABLED_COND (noPanoramiXExtension || PanoramiXExtensionDisabledHack)
+#else
+ #define PANORAMIX_DISABLED_COND TRUE
+#endif
+
+#ifdef RANDR
+ #define RRXINERAMA_DISABLED_COND noRRXineramaExtension
+#else
+ #define RRXINERAMA_DISABLED_COND TRUE
+#endif
+
+/*
+ * Define this to force the dispatcher
+ * to always use the dumb scheduler.
+ */
+
+#undef DISABLE_SMART_SCHEDULE
+
+int nxagentUserDefinedFontPath = 0;
+
+/*
+ * From X11/ImUtil.c.
+ */
+
+extern int _XGetBitsPerPixel(Display *dpy, int depth);
+
+extern char dispatchExceptionAtReset;
+
+extern const char *__progname;
+
+char nxagentDisplayName[1024];
+Bool nxagentSynchronize = False;
+
+char nxagentShadowDisplayName[1024] = {0};
+
+char nxagentWindowName[256];
+char nxagentDialogName[256];
+char nxagentSessionId[256] = {0};
+char *nxagentOptionFile;
+
+Bool nxagentFullGeneration = False;
+int nxagentDefaultClass = TrueColor;
+Bool nxagentUserDefaultClass = False;
+int nxagentDefaultDepth;
+Bool nxagentUserDefaultDepth = False;
+struct UserGeometry nxagentUserGeometry = {0, 0, 0, 0, 0};
+Bool nxagentUserBorderWidth = False;
+int nxagentNumScreens = 0;
+Bool nxagentDoDirectColormaps = False;
+Window nxagentParentWindow = 0;
+Bool nxagentIpaq = False;
+
+int nxagentLockDeferLevel = 0;
+
+Bool nxagentResizeDesktopAtStartup = False;
+
+Bool nxagentUseNXTrans = False;
+Bool nxagentForceNXTrans = False;
+
+int nxagentMaxAllowedResets = 0;
+
+char *nxagentKeyboard = NULL;
+
+Bool nxagentOnce = True;
+
+int nxagentRemoteMajor = -1;
+
+static void nxagentParseOptionString(char*);
+
+/*
+ * Get the caption to be used for helper dialogs
+ * from agent's window name passed as parameter.
+ */
+
+static int nxagentGetDialogName(void);
+
+char nxagentVerbose = 0;
+
+char *nxagentKeystrokeFile = NULL;
+
+int ddxProcessArgument(int argc, char *argv[], int i)
+{
+ /*
+ * Ensure that the options are set to their defaults.
+ */
+
+ static Bool resetOptions = True;
+
+ if (resetOptions == True)
+ {
+ char *envOptions = NULL;
+ char *envDisplay = NULL;
+ int j;
+
+ nxagentInitOptions();
+
+ resetOptions = False;
+
+ /*
+ * Ensure the correct order of options evaluation:
+ * the environment first, then those included in
+ * the options file and, last, the command line
+ * options.
+ */
+
+ envDisplay = getenv("DISPLAY");
+
+ if (envDisplay != NULL && strlen(envDisplay) == 0)
+ {
+ envDisplay = NULL;
+ }
+
+ for (j = 0; j < argc; j++)
+ {
+ if ((!strcmp(argv[j], "-display")) && (j + 1 < argc))
+ {
+ envOptions = malloc(strlen(argv[j + 1]) + 1);
+
+ if (envOptions != NULL)
+ {
+ envOptions = strcpy(envOptions, argv[j + 1]);
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n");
+ }
+ #endif
+
+ break;
+ }
+ }
+
+ if ((envOptions == NULL) && (envDisplay != NULL))
+ {
+ envOptions = malloc(strlen(envDisplay) + 1);
+
+ if (envOptions != NULL)
+ {
+ envOptions = strcpy(envOptions, envDisplay);
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n");
+ }
+ #endif
+ }
+
+ if (envOptions != NULL)
+ {
+ nxagentParseOptionString(envOptions);
+
+ free(envOptions);
+ }
+
+ for (j = 0; j < argc; j++)
+ {
+ if ((!strcmp(argv[j], "-options") || !strcmp(argv[j], "-option")) && j + 1 < argc)
+ {
+ if (nxagentOptionFile)
+ {
+ nxagentOptionFile = (char *) realloc(nxagentOptionFile, strlen(argv[j + 1]) + 1);
+ }
+ else
+ {
+ nxagentOptionFile = (char *) malloc(strlen(argv[j + 1]) +1);
+ }
+
+ if (nxagentOptionFile != NULL)
+ {
+ nxagentOptionFile = strcpy(nxagentOptionFile, argv[j + 1]);
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "ddxProcessArgument: WARNING! failed string allocation.\n");
+ }
+ #endif
+
+ break;
+ }
+ }
+
+ if (nxagentOptionFile)
+ {
+ nxagentProcessOptionsFile();
+ }
+ }
+
+ if (!strcmp(argv[i], "-B"))
+ {
+ #ifdef TEST
+ fprintf(stderr, "ddxProcessArgument: Checking the NX binder option.\n");
+ #endif
+
+ if (nxagentCheckBinder(argc, argv, i) > 0)
+ {
+ /*
+ * We are going to run the agent with the
+ * 'binder' option. Go straight to the
+ * proxy loop.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "ddxProcessArgument: Entering the NX proxy binder loop.\n");
+ #endif
+
+ nxagentBinderLoop();
+
+ /*
+ * This will make an exit.
+ */
+
+ nxagentBinderExit(0);
+ }
+ else
+ {
+ /*
+ * Exit with an error.
+ */
+
+ nxagentBinderExit(1);
+ }
+ }
+
+ if (!strcmp(argv[i], "-display"))
+ {
+ if (++i < argc)
+ {
+ strncpy(nxagentDisplayName, argv[i], 1023);
+
+ nxagentDisplayName[1023] = '\0';
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-id"))
+ {
+ if (++i < argc)
+ {
+ strncpy(nxagentSessionId, argv[i], 255);
+
+ *(nxagentSessionId + 255) = '\0';
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ /*
+ * This had to be '-options' since the beginning
+ * but was '-option' by mistake. Now we have to
+ * handle the backward compatibility.
+ */
+
+ if (!strcmp(argv[i], "-options") || !strcmp(argv[i], "-option"))
+ {
+ if (++i < argc)
+ {
+ int size;
+
+ if (nxagentOptionFile != NULL)
+ {
+ free(nxagentOptionFile);
+
+ nxagentOptionFile = NULL;
+ }
+
+ if ((size = strlen(argv[i])) < 1024)
+ {
+ if ((nxagentOptionFile = malloc(size + 1)) == NULL)
+ {
+ FatalError("malloc failed");
+ }
+
+ strncpy(nxagentOptionFile, argv[i], size);
+
+ nxagentOptionFile[size] = '\0';
+ }
+ else
+ {
+ /*
+ * It is useless to store the file name
+ * that has just been truncated.
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "ddxProcessArgument: WARNING! Option file name "
+ "too long. It will be ignored.\n");
+ #endif
+ }
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-sync")) {
+ nxagentSynchronize = True;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-full")) {
+ nxagentFullGeneration = True;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-class")) {
+ if (++i < argc) {
+ if (!strcmp(argv[i], "StaticGray")) {
+ nxagentDefaultClass = StaticGray;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ else if (!strcmp(argv[i], "GrayScale")) {
+ nxagentDefaultClass = GrayScale;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ else if (!strcmp(argv[i], "StaticColor")) {
+ nxagentDefaultClass = StaticColor;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ else if (!strcmp(argv[i], "PseudoColor")) {
+ nxagentDefaultClass = PseudoColor;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ else if (!strcmp(argv[i], "TrueColor")) {
+ nxagentDefaultClass = TrueColor;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ else if (!strcmp(argv[i], "DirectColor")) {
+ nxagentDefaultClass = DirectColor;
+ nxagentUserDefaultClass = True;
+ return 2;
+ }
+ }
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-cc")) {
+ if (++i < argc && sscanf(argv[i], "%i", &nxagentDefaultClass) == 1) {
+ if (nxagentDefaultClass >= 0 && nxagentDefaultClass <= 5) {
+ nxagentUserDefaultClass = True;
+ /* lex the OS layer process it as well, so return 0 */
+ }
+ }
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-depth")) {
+ if (++i < argc && sscanf(argv[i], "%i", &nxagentDefaultDepth) == 1) {
+ if (nxagentDefaultDepth > 0) {
+ nxagentUserDefaultDepth = True;
+ return 2;
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * These options are now useless and are
+ * parsed only for compatibility with
+ * older versions.
+ */
+
+ if (!strcmp(argv[i], "-fast") ||
+ !strcmp(argv[i], "-slow") ||
+ !strcmp(argv[i], "-hint") ||
+ !strcmp(argv[i], "-sss"))
+ {
+ fprintf(stderr, "Warning: Ignoring deprecated command line option '%s'.\n",
+ argv[i]);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-backingstore"))
+ {
+ if (++i < argc)
+ {
+ if (!strcmp(argv[i], "0"))
+ {
+ nxagentChangeOption(BackingStore, BackingStoreNever);
+ }
+ else
+ {
+ nxagentChangeOption(BackingStore, BackingStoreForce);
+ }
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-streaming"))
+ {
+ if (++i < argc)
+ {
+ if (!strcmp(argv[i], "0"))
+ {
+ nxagentChangeOption(Streaming, 0);
+ }
+ else
+ {
+ nxagentChangeOption(Streaming, 1);
+ }
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-defer"))
+ {
+ int level;
+
+ if (++i < argc &&
+ sscanf(argv[i], "%i", &level) == 1 &&
+ level >= 0 && level <= 2)
+ {
+ if (nxagentOption(Shadow) == 0)
+ {
+ nxagentChangeOption(DeferLevel, level);
+
+ /*
+ * The defer level set with the command
+ * line is not changed when the session
+ * is resumed.
+ */
+
+ nxagentLockDeferLevel = 1;
+ }
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-irlimit"))
+ {
+ int limit;
+
+ if (++i < argc &&
+ sscanf(argv[i], "%i", &limit) == 1)
+ {
+ nxagentChangeOption(ImageRateLimit, limit);
+
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-tile"))
+ {
+ int width;
+ int height;
+
+ if (++i < argc &&
+ sscanf(argv[i], "%ix%i", &width, &height) == 2 &&
+ width >= 32 && height >= 32)
+ {
+ nxagentChangeOption(TileWidth, width);
+ nxagentChangeOption(TileHeight, height);
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (strcmp(argv[i], "-fp") == 0)
+ {
+ if(++i < argc)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "ddxProcessArgument: User defined font path [%s].\n", argv[i]);
+ #endif
+
+ nxagentUserDefinedFontPath = 1;
+
+ defaultFontPath = argv[i];
+ }
+ else
+ {
+ UseMsg();
+ }
+ }
+
+ if (!strcmp(argv[i], "-geometry"))
+ {
+ if (++i < argc)
+ {
+ if (!strcmp(argv[i],"fullscreen"))
+ {
+ nxagentChangeOption(Fullscreen, True);
+
+ nxagentChangeOption(AllScreens, True);
+ }
+ else if (!strcmp(argv[i],"ipaq"))
+ {
+ nxagentChangeOption(Fullscreen, True);
+
+ nxagentChangeOption(AllScreens, True);
+
+ nxagentIpaq = True;
+ }
+ else
+ {
+ if (nxagentUserGeometry.flag == 0)
+ {
+ nxagentUserGeometry.flag = XParseGeometry(argv[i],
+ &nxagentUserGeometry.X,
+ &nxagentUserGeometry.Y,
+ &nxagentUserGeometry.Width,
+ &nxagentUserGeometry.Height);
+ }
+ }
+
+ if (nxagentUserGeometry.flag || (nxagentOption(Fullscreen) == 1)) return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-bw"))
+ {
+ int BorderWidth;
+
+ if (++i < argc && sscanf(argv[i], "%i", &BorderWidth) == 1)
+ {
+ nxagentChangeOption(BorderWidth, BorderWidth);
+
+ if (nxagentOption(BorderWidth) >= 0)
+ {
+ nxagentUserBorderWidth = True;
+
+ return 2;
+ }
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-name"))
+ {
+ if (++i < argc)
+ {
+ strncpy(nxagentWindowName, argv[i], 255);
+
+ *(nxagentWindowName + 255) = '\0';
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-scrns")) {
+ if (++i < argc && sscanf(argv[i], "%i", &nxagentNumScreens) == 1) {
+ if (nxagentNumScreens > 0) {
+ if (nxagentNumScreens > MAXSCREENS) {
+ ErrorF("Maximum number of screens is %d.\n", MAXSCREENS);
+ nxagentNumScreens = MAXSCREENS;
+ }
+ return 2;
+ }
+ }
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-install")) {
+ nxagentDoDirectColormaps = True;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-parent")) {
+ if (++i < argc) {
+ nxagentParentWindow = (XID) strtol (argv[i], (char**)NULL, 0);
+ return 2;
+ }
+ }
+
+ if (!strcmp(argv[i], "-forcenx")) {
+ nxagentForceNXTrans = True;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-norootlessexit")) {
+ nxagentChangeOption(NoRootlessExit, True);
+ return 1;
+ }
+
+
+ if (!strcmp(argv[i], "-noonce"))
+ {
+ nxagentOnce = False;
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-kbtype") ||
+ !strcmp(argv[i], "-keyboard"))
+ {
+ if (++i < argc)
+ {
+ int size;
+
+ if (nxagentKeyboard != NULL)
+ {
+ free(nxagentKeyboard);
+
+ nxagentKeyboard = NULL;
+ }
+
+ if ((size = strlen(argv[i])) < 256)
+ {
+ if ((nxagentKeyboard = malloc(size + 1)) == NULL)
+ {
+ FatalError("malloc failed");
+ }
+
+ strncpy(nxagentKeyboard, argv[i], size);
+
+ nxagentKeyboard[size] = '\0';
+ }
+ #ifdef WARNING
+ else
+ {
+ /*
+ * it is useless to remember a kbtype
+ * option that has just been truncated.
+ */
+
+ fprintf(stderr, "ddxProcessArgument: WARNING! Option [%s] too long. "
+ "It will be ignored.\n", argv[i]);
+ }
+ #endif
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-extensions"))
+ {
+ return 1;
+ }
+
+ #ifdef RENDER
+ if (!strcmp(argv[i], "-norender"))
+ {
+ nxagentRenderEnable = False;
+
+ return 1;
+ }
+ #endif
+
+ if (!strcmp(argv[i], "-nocomposite"))
+ {
+ nxagentChangeOption(Composite, 0);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-nodamage"))
+ {
+ nxagentChangeOption(UseDamage, 0);
+
+ return 1;
+ }
+
+ /*
+ * The original -noreset option, disabling
+ * dispatchExceptionAtReset, is the default.
+ * Use this option to restore the original
+ * behaviour.
+ */
+
+ if (!strcmp(argv[i], "-reset"))
+ {
+ nxagentChangeOption(Reset, True);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-persistent"))
+ {
+ nxagentChangeOption(Persistent, True);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-nopersistent"))
+ {
+ nxagentChangeOption(Persistent, False);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-noshmem"))
+ {
+ nxagentChangeOption(SharedMemory, False);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-shmem"))
+ {
+ nxagentChangeOption(SharedMemory, True);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-noignore"))
+ {
+ nxagentChangeOption(DeviceControl, True);
+
+ nxagentChangeOption(DeviceControlUserDefined , True);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-nokbreset"))
+ {
+ nxagentChangeOption(ResetKeyboardAtResume, False);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-noxkblock"))
+ {
+ nxagentChangeOption(InhibitXkb, 0);
+
+ return 1;
+ }
+
+ /*
+ * Enable pseudo-rootless mode.
+ */
+
+ if (!strcmp(argv[i], "-R"))
+ {
+ if (nxagentOption(Binder) == UNDEFINED ||
+ nxagentOption(Desktop) == UNDEFINED ||
+ nxagentOption(Rootless) == UNDEFINED)
+ {
+ nxagentChangeOption(Binder, False);
+ nxagentChangeOption(Desktop, False);
+ nxagentChangeOption(Rootless, True);
+ }
+ return 1;
+ }
+
+ /*
+ * Enable the "desktop" mode. This is
+ * the default.
+ */
+
+ if (!strcmp(argv[i], "-D"))
+ {
+ nxagentChangeOption(Binder, False);
+ nxagentChangeOption(Rootless, False);
+ nxagentChangeOption(Desktop, True);
+
+ return 1;
+ }
+
+ /*
+ * Enable the "shadow" mode.
+ */
+
+ if (!strcmp(argv[i], "-S"))
+ {
+ nxagentChangeOption(Shadow, 1);
+ nxagentChangeOption(DeferLevel, 0);
+ nxagentChangeOption(Persistent, 0);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-shadow"))
+ {
+ if (++i < argc)
+ {
+ strncpy(nxagentShadowDisplayName, argv[i], 1023);
+
+ if (strcmp(nxagentShadowDisplayName, "") == 0)
+ {
+ FatalError("Invalid shadow display option");
+ }
+
+ *(nxagentShadowDisplayName + 1023) = '\0';
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+
+ if (!strcmp(argv[i], "-shadowmode"))
+ {
+ if (++i < argc)
+ {
+ if (!strcmp(argv[i], "0"))
+ {
+ nxagentChangeOption(ViewOnly, 1);
+ }
+ else
+ {
+ nxagentChangeOption(ViewOnly, 0);
+ }
+
+ return 2;
+ }
+
+ return 0;
+ }
+
+ /*
+ * Enable the auto-disconnect timeout.
+ */
+
+ if (!strcmp(argv[i], "-timeout"))
+ {
+ int seconds;
+
+ if (++i < argc && sscanf(argv[i], "%i", &seconds) == 1)
+ {
+ if (seconds >= 0)
+ {
+ if (seconds > 0 && seconds < 60)
+ {
+ seconds = 60;
+ }
+
+ nxagentChangeOption(Timeout, seconds);
+
+ return 2;
+ }
+ }
+
+ return 0;
+ }
+
+ /*
+ * The return value for -query, -broadcast and
+ * -indirect must be 0 to let the dix layer pro-
+ * cess these options.
+ */
+
+ if (!strcmp(argv[i], "-query"))
+
+ {
+ nxagentChangeOption(Desktop, True);
+ nxagentChangeOption(Xdmcp, True);
+
+ nxagentMaxAllowedResets = 0;
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-broadcast"))
+
+ {
+ nxagentChangeOption(Desktop, True);
+ nxagentChangeOption(Xdmcp, True);
+
+ nxagentMaxAllowedResets = 0;
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-indirect"))
+ {
+ nxagentChangeOption(Desktop, True);
+ nxagentChangeOption(Xdmcp, True);
+
+ nxagentMaxAllowedResets = 1;
+
+ return 0;
+ }
+
+ if (!strcmp(argv[i], "-noshpix"))
+ {
+ nxagentChangeOption(SharedPixmaps, False);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-shpix"))
+ {
+ nxagentChangeOption(SharedPixmaps, True);
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-clipboard"))
+ {
+ if ((!strcmp(argv[i+1], "both")) || (!strcmp(argv[i+1], "1")))
+ {
+ nxagentChangeOption(Clipboard, ClipboardBoth);
+ }
+ else if (!strcmp(argv[i+1], "client"))
+ {
+ nxagentChangeOption(Clipboard, ClipboardClient);
+ }
+ else if (!strcmp(argv[i+1], "server"))
+ {
+ nxagentChangeOption(Clipboard, ClipboardServer);
+ }
+ else if ((!strcmp(argv[i+1], "none")) || (!strcmp(argv[i+1], "1")))
+ {
+ nxagentChangeOption(Clipboard, ClipboardNone);
+ }
+ else
+ {
+ nxagentChangeOption(Clipboard, ClipboardBoth);
+ }
+
+ return 2;
+ }
+
+ if (!strcmp(argv[i], "-bs"))
+ {
+ nxagentChangeOption(BackingStore, BackingStoreNever);
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-verbose"))
+ {
+ nxagentVerbose = 1;
+
+ return 1;
+ }
+
+ if (!strcmp(argv[i], "-keystrokefile"))
+ {
+ if (i + 1 < argc)
+ {
+ if (NULL != (nxagentKeystrokeFile = strdup(argv[i + 1])))
+ {
+ return 2;
+ } else {
+ FatalError("malloc failed");
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * Disable Xinerama (i.e. fake it in Screen.c) if somehow Xinerama support
+ * has been disabled on the cmdline.
+ */
+ if (PANORAMIX_DISABLED_COND && RRXINERAMA_DISABLED_COND)
+ nxagentChangeOption(Xinerama, 0);
+
+ return 0;
+}
+
+static void nxagentParseOptions(char *name, char *value)
+{
+ int size, argc;
+
+ char *argv[2] = { NULL, NULL };
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentParseOptions: Processing option '%s' = '%s'.\n",
+ validateString(name), validateString(value));
+ #endif
+
+ if (!strcmp(name, "kbtype") ||
+ !strcmp(name, "keyboard") ||
+ !strcmp(name, "id") ||
+ !strcmp(name, "display") ||
+ !strcmp(name, "clipboard") ||
+ !strcmp(name, "geometry") ||
+ !strcmp(name, "option") ||
+ !strcmp(name, "options") ||
+ !strcmp(name, "shadow") ||
+ !strcmp(name, "shadowmode") ||
+ !strcmp(name, "streaming") ||
+ !strcmp(name, "defer") ||
+ !strcmp(name, "tile"))
+ {
+ argv[1] = value;
+
+ argc = 2;
+ }
+ else if (!strcmp(name, "R") && !strcmp(value, "1"))
+ {
+ argc = 1;
+ }
+ else if (!strcmp(name, "fast") || !strcmp(name, "slow"))
+ {
+ fprintf(stderr, "Warning: Ignoring deprecated option '%s'.\n", name);
+
+ return;
+ }
+ else if (!strcmp(name, "render"))
+ {
+ if (nxagentReconnectTrap == True)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentParseOptions: Ignoring option 'render' at reconnection.\n");
+ #endif
+ }
+ else if (nxagentRenderEnable == UNDEFINED)
+ {
+ if (!strcmp(value, "1"))
+ {
+ nxagentRenderEnable = True;
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentRenderEnable = False;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'render'.\n",
+ validateString(value));
+ }
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "state"))
+ {
+ setStatePath(value);
+ return;
+ }
+ else if (!strcmp(name, "fullscreen"))
+ {
+ if (nxagentReconnectTrap == True)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentParseOptions: Ignoring option 'fullscreen' at reconnection.\n");
+ #endif
+ }
+ else if (!strcmp(value, "1"))
+ {
+ nxagentChangeOption(Fullscreen, True);
+
+ nxagentChangeOption(AllScreens, True);
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(Fullscreen, False);
+
+ nxagentChangeOption(AllScreens, False);
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'fullscreen'.\n",
+ validateString(value));
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "shpix"))
+ {
+ if (!strcmp(value, "1"))
+ {
+ nxagentChangeOption(SharedPixmaps, True);
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(SharedPixmaps, False);
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'shpix'.\n",
+ validateString(value));
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "shmem"))
+ {
+ if (!strcmp(value, "1"))
+ {
+ nxagentChangeOption(SharedMemory, True);
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(SharedMemory, False);
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'shmem'.\n",
+ validateString(value));
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "composite"))
+ {
+ if (!strcmp(value, "1"))
+ {
+ nxagentChangeOption(Composite, 1);
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(Composite, 0);
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'composite'.\n",
+ validateString(value));
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "xinerama"))
+ {
+#if !defined(PANORAMIX) && !defined(RANDR)
+ nxagentChangeOption(Xinerama, 0);
+ fprintf(stderr, "Warning: No Xinerama support compiled into %s.\n", __progname);
+ return;
+#else
+ if (PANORAMIX_DISABLED_COND && RRXINERAMA_DISABLED_COND)
+ {
+ nxagentChangeOption(Xinerama, 0);
+ fprintf(stderr, "Warning: XINERAMA extension has been disabled on %s startup.\n", __progname);
+ return;
+ }
+
+ if (!strcmp(value, "1"))
+ {
+ nxagentChangeOption(Xinerama, 1);
+ return;
+ }
+ else if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(Xinerama, 0);
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'xinerama'.\n",
+ validateString(value));
+ }
+ return;
+#endif
+ }
+ else if (!strcmp(name, "resize"))
+ {
+ if (nxagentOption(DesktopResize) == 0 || strcmp(value, "0") == 0)
+ {
+ nxagentResizeDesktopAtStartup = 0;
+ }
+ else if (strcmp(value, "1") == 0)
+ {
+ nxagentResizeDesktopAtStartup = 1;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Ignoring bad value '%s' for option 'resize'.\n",
+ validateString(value));
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "backingstore"))
+ {
+ if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(BackingStore, BackingStoreNever);
+ }
+ else
+ {
+ nxagentChangeOption(BackingStore, BackingStoreForce);
+ }
+
+ return;
+ }
+ else if (!strcmp(name, "menu"))
+ {
+ if (!strcmp(value, "0"))
+ {
+ nxagentChangeOption(Menu, 0);
+ }
+ else
+ {
+ nxagentChangeOption(Menu, 1);
+ }
+
+ return;
+ }
+ else if (strcmp(name, "shadowuid") == 0)
+ {
+ nxagentShadowUid = atoi(value);
+
+ return;
+ }
+ else if (strcmp(name, "clients") == 0)
+ {
+ strcpy(nxagentClientsLogName, value);
+
+ return;
+ }
+ else if (strcmp(name, "client") == 0)
+ {
+ if (strcmp(value, "winnt") == 0 || strcmp(value, "windows") == 0)
+ {
+ nxagentChangeOption(ClientOs, ClientOsWinnt);
+ }
+ else if (strcmp(value, "linux") == 0)
+ {
+ nxagentChangeOption(ClientOs, ClientOsLinux);
+ }
+ else if (strcmp(value, "solaris") == 0)
+ {
+ nxagentChangeOption(ClientOs, ClientOsSolaris);
+ }
+ else if (strcmp(value, "macosx") == 0)
+ {
+ nxagentChangeOption(ClientOs, ClientOsMac);
+ }
+
+ return;
+ }
+ else if (strcmp(name, "copysize") == 0)
+ {
+ nxagentChangeOption(CopyBufferSize, atoi(value));
+
+ return;
+ }
+ else if (strcmp(name, "clipboard") == 0)
+ {
+ if ((strcmp(value, "both") == 0) || (strcmp(value, "1") == 0))
+ {
+ nxagentChangeOption(Clipboard, ClipboardBoth);
+ }
+ else if (strcmp(value, "client") == 0)
+ {
+ nxagentChangeOption(Clipboard, ClipboardClient);
+ }
+ else if (strcmp(value, "server") == 0)
+ {
+ nxagentChangeOption(Clipboard, ClipboardServer);
+ }
+ else if ((strcmp(value, "none") == 0) || (strcmp(value, "0") == 0))
+ {
+ nxagentChangeOption(Clipboard, ClipboardNone);
+ }
+ else
+ {
+ nxagentChangeOption(Clipboard, ClipboardBoth);
+ }
+ }
+ else if (!strcmp(name, "sleep"))
+ {
+ long sleep_parse = 0;
+
+ errno = 0;
+ sleep_parse = strtol(value, NULL, 10);
+
+ if ((errno) && (0 == sleep_parse))
+ {
+ fprintf(stderr, "nxagentParseOptions: Unable to convert value [%s] of option [%s]. "
+ "Ignoring option.\n",
+ validateString(value), validateString(name));
+
+ return;
+ }
+
+ if ((long) UINT_MAX < sleep_parse)
+ {
+ sleep_parse = UINT_MAX;
+
+ fprintf(stderr, "nxagentParseOptions: Warning: value [%s] of option [%s] "
+ "out of range, clamped to [%lu].\n",
+ validateString(value), validateString(name), sleep_parse);
+ }
+
+ if (0 > sleep_parse)
+ {
+ sleep_parse = 0;
+
+ fprintf(stderr, "nxagentParseOptions: Warning: value [%s] of option [%s] "
+ "out of range, clamped to [%lu].\n",
+ validateString(value), validateString(name), sleep_parse);
+ }
+
+ nxagentChangeOption(SleepTime, sleep_parse);
+
+ return;
+ }
+ else if (!strcmp(name, "tolerancechecks"))
+ {
+ if (strcmp(value, "strict") == 0)
+ {
+ nxagentChangeOption(ReconnectTolerance, ToleranceChecksStrict);
+ }
+ else if (strcmp(value, "safe") == 0)
+ {
+ nxagentChangeOption(ReconnectTolerance, ToleranceChecksSafe);
+ }
+ else if (strcmp(value, "risky") == 0)
+ {
+ nxagentChangeOption(ReconnectTolerance, ToleranceChecksRisky);
+ }
+ else if (strcmp(value, "bypass") == 0)
+ {
+ nxagentChangeOption(ReconnectTolerance, ToleranceChecksBypass);
+ }
+ else
+ {
+ /*
+ * Check for a matching integer. Or any integer, really.
+ */
+ long tolerance_parse = 0;
+
+ errno = 0;
+ tolerance_parse = strtol(value, NULL, 10);
+
+ if ((errno) && (0 == tolerance_parse))
+ {
+ fprintf(stderr, "nxagentParseOptions: Unable to convert value [%s] of option [%s]. "
+ "Ignoring option.\n",
+ validateString(value), validateString(name));
+
+ return;
+ }
+
+ if ((long) UINT_MAX < tolerance_parse)
+ {
+ tolerance_parse = UINT_MAX;
+
+ fprintf(stderr, "nxagentParseOptions: Warning: value [%s] of option [%s] "
+ "out of range, clamped to [%lu].\n",
+ validateString(value), validateString(name), tolerance_parse);
+ }
+
+ if (0 > tolerance_parse)
+ {
+ tolerance_parse = 0;
+
+ fprintf(stderr, "nxagentParseOptions: Warning: value [%s] of option [%s] "
+ "out of range, clamped to [%lu].\n",
+ validateString(value), validateString(name), tolerance_parse);
+ }
+
+ #ifdef TEST
+ switch (tolerance_parse) {
+ case ToleranceChecksStrict:
+ case ToleranceChecksSafe:
+ case ToleranceChecksRisky:
+ case ToleranceChecksBypass:
+ break;
+ default:
+ fprintf(stderr, "nxagentParseOptions: Warning: value [%s] of "
+ "option [%s] unknown, will be mapped to "
+ "\"Bypass\" [%u] value internally.\n",
+ validateString(value), validateString(name),
+ (unsigned int)ToleranceChecksBypass);
+ }
+ #endif
+
+ nxagentChangeOption(ReconnectTolerance, tolerance_parse);
+ }
+
+ return;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentParseOptions: Ignored option [%s] with value [%s].\n",
+ validateString(name), validateString(value));
+ #endif
+
+ return;
+ }
+
+ /*
+ * Before passing the not yet evaluated options
+ * to ddxProcessArgument(), we have to add a dash
+ * as prefix.
+ */
+
+ if ((size = strlen(name) + 1) > 1)
+ {
+ if ((argv[0] = malloc(size + 1)) == NULL)
+ {
+ fprintf(stderr, "Warning: Ignoring option '%s' due to lack of memory.\n",
+ name);
+
+ return;
+ }
+
+ *argv[0] = '-';
+
+ memcpy(argv[0] + 1, name, size);
+ }
+
+ ddxProcessArgument(argc, argv, 0);
+
+ free(argv[0]);
+}
+
+static void nxagentParseOptionString(char *string)
+{
+ char *value = NULL;
+ char *option = NULL;
+ char *delimiter = NULL;
+
+ /*
+ * Remove the port specification.
+ */
+
+ delimiter = rindex(string, ':');
+
+ if (delimiter)
+ {
+ *delimiter = 0;
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Option file doesn't contain a port specification.\n");
+ }
+
+ while ((option = strtok(option ? NULL : string, ",")))
+ {
+ delimiter = rindex(option, '=');
+
+ if (delimiter)
+ {
+ *delimiter = 0;
+ value = delimiter + 1;
+ }
+ else
+ {
+ value = NULL;
+ }
+
+ nxagentParseOptions(option, value);
+ }
+}
+
+void nxagentProcessOptionsFile()
+{
+ FILE *file;
+ char *data;
+
+ int offset;
+ int size;
+
+ int sizeOfFile;
+ int maxFileSize = 1024;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentProcessOptionsFile: Going to process option the file [%s].\n",
+ validateString(nxagentOptionFile));
+ #endif
+
+ /*
+ * Init statePath
+ */
+ setStatePath("");
+
+ if (nxagentOptionFile == NULL)
+ {
+ return;
+ }
+
+ if ((file = fopen(nxagentOptionFile, "r")) == NULL)
+ {
+ fprintf(stderr, "Warning: Couldn't open option file '%s'. Error is '%s'.\n",
+ validateString(nxagentOptionFile), strerror(errno));
+
+ goto nxagentProcessOptionsFileExit;
+ }
+
+ if (fseek(file, 0, SEEK_END) != 0)
+ {
+ fprintf(stderr, "Warning: Couldn't position inside option file '%s'. Error is '%s'.\n",
+ validateString(nxagentOptionFile), strerror(errno));
+
+ goto nxagentProcessOptionsFileClose;
+ }
+
+ if ((sizeOfFile = ftell(file)) == -1)
+ {
+ fprintf(stderr, "Warning: Couldn't get the size of option file '%s'. Error is '%s'.\n",
+ validateString(nxagentOptionFile), strerror(errno));
+
+ goto nxagentProcessOptionsFileClose;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentProcessOptionsFile: Processing option file [%s].\n",
+ validateString(nxagentOptionFile));
+ #endif
+
+ rewind(file);
+
+ if (sizeOfFile > maxFileSize)
+ {
+ fprintf(stderr, "Warning: Maximum file size exceeded for options '%s'.\n",
+ validateString(nxagentOptionFile));
+
+ goto nxagentProcessOptionsFileClose;
+ }
+
+ if ((data = malloc(sizeOfFile + 1)) == NULL)
+ {
+ fprintf(stderr, "Warning: Memory allocation failed processing file '%s'.\n",
+ validateString(nxagentOptionFile));
+
+ goto nxagentProcessOptionsFileClose;
+ }
+
+ offset = 0;
+ size = 0;
+
+ for (;;)
+ {
+ size_t result = fread(data + offset, 1, sizeOfFile, file);
+
+ if (ferror(file) != 0)
+ {
+ fprintf(stderr, "Warning: Error reading the option file '%s'.\n",
+ validateString(nxagentOptionFile));
+
+ goto nxagentProcessOptionsFileFree;
+ }
+
+ size += result;
+ offset += result;
+
+ if (feof(file) != 0 || (size == sizeOfFile))
+ {
+ break;
+ }
+ }
+
+ if (size != sizeOfFile)
+ {
+ fprintf(stderr, "Warning: Premature end of option file '%s' while reading.\n",
+ validateString(nxagentOptionFile));
+
+ goto nxagentProcessOptionsFileFree;
+ }
+
+ /*
+ * Truncate the buffer to the first line.
+ */
+
+ for (offset = 0; (offset < sizeOfFile) && (data[offset] != '\n'); offset++);
+
+ data[offset] = 0;
+
+ nxagentParseOptionString(data);
+
+nxagentProcessOptionsFileFree:
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+
+nxagentProcessOptionsFileClose:
+
+ if (fclose(file) != 0)
+ {
+ fprintf(stderr, "Warning: Couldn't close option file '%s'. Error is '%s'.\n",
+ validateString(nxagentOptionFile), strerror(errno));
+ }
+
+nxagentProcessOptionsFileExit:
+
+ return;
+}
+
+/*
+ * FIXME: Transport initialization, shouldn't depend upon
+ * argv[], because we call it at every reconnection.
+ */
+
+Bool nxagentPostProcessArgs(char* name, Display* dpy, Screen* scr)
+{
+ Bool useNXTrans = False;
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentPostProcessArgs: Watchpoint 2.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ if ((nxagentOption(Rootless) == 1) && nxagentOption(Fullscreen) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "WARNING: Ignoring fullscreen option for rootless session.\n");
+ #endif
+
+ nxagentChangeOption(Fullscreen, False);
+ }
+
+ /*
+ * Ensure we have a valid name for children dialogs.
+ */
+
+ nxagentGetDialogName();
+
+ /*
+ * Ensure we have a valid name for window name.
+ */
+
+ if (*nxagentWindowName == '\0')
+ {
+ strncpy(nxagentWindowName, "NX", 255);
+
+ *(nxagentWindowName + 255) = '\0';
+ }
+
+ /*
+ * Note that use of NX packed images as well as
+ * render extension could be later disabled due
+ * to the fact that session is running nested
+ * in a nxagent server.
+ */
+
+ if (nxagentForceNXTrans)
+ {
+ useNXTrans = True;
+ }
+ else if ((strncasecmp(name, "nx/", 3) == 0) ||
+ (strncasecmp(name, "nx:", 3) == 0) ||
+ (strncasecmp(name, "nx,", 3) == 0) ||
+ (strcasecmp(name, "nx") == 0))
+ {
+ useNXTrans = True;
+ }
+
+ if (useNXTrans == True)
+ {
+ unsigned int linkType = LINK_TYPE_NONE;
+
+ unsigned int localMajor = 0;
+ unsigned int localMinor = 0;
+ unsigned int localPatch = 0;
+
+ unsigned int remoteMajor = 0;
+ unsigned int remoteMinor = 0;
+ unsigned int remotePatch = 0;
+
+ int splitTimeout = 0;
+ int motionTimeout = 0;
+
+ int splitMode = 0;
+ int splitSize = 0;
+
+ unsigned int packMethod = PACK_NONE;
+ unsigned int packQuality = 9;
+
+ int dataLevel = 0;
+ int streamLevel = 0;
+ int deltaLevel = 0;
+
+ unsigned int loadCache = 0;
+ unsigned int saveCache = 0;
+ unsigned int startupCache = 0;
+
+ unsigned int enableClient = 0;
+ unsigned int enableServer = 0;
+
+ unsigned int clientSegment = 0;
+ unsigned int serverSegment = 0;
+
+ unsigned int clientSize = 0;
+ unsigned int serverSize = 0;
+
+ if (NXGetControlParameters(dpy, &linkType, &localMajor, &localMinor,
+ &localPatch, &remoteMajor, &remoteMinor, &remotePatch,
+ &splitTimeout, &motionTimeout, &splitMode, &splitSize,
+ &packMethod, &packQuality, &dataLevel, &streamLevel,
+ &deltaLevel, &loadCache, &saveCache, &startupCache) == 0)
+ {
+ fprintf(stderr, "Warning: Failed to get the control parameters.\n");
+ }
+
+ nxagentChangeOption(LinkType, linkType);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPostProcessArgs: Got local version [%d.%d.%d] remote version [%d.%d.%d].\n",
+ localMajor, localMinor, localPatch, remoteMajor, remoteMinor, remotePatch);
+
+ fprintf(stderr, "nxagentPostProcessArgs: Got split timeout [%d] motion timeout [%d].\n",
+ splitTimeout, motionTimeout);
+
+ fprintf(stderr, "nxagentPostProcessArgs: Got split mode [%d] split size [%d].\n",
+ splitMode, splitSize);
+
+ fprintf(stderr, "nxagentPostProcessArgs: Got preferred pack method [%d] and quality [%d].\n",
+ packMethod, packQuality);
+ #endif
+
+ if (remoteMajor < 2)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPostProcessArgs: WARNING! Using backward compatible alpha encoding.\n");
+ #endif
+
+ nxagentAlphaCompat = 1;
+ }
+ else
+ {
+ nxagentAlphaCompat = 0;
+ }
+
+ nxagentRemoteMajor = remoteMajor;
+
+ if (nxagentPackMethod == -1)
+ {
+ nxagentPackMethod = packMethod;
+ }
+
+ if (nxagentPackQuality == -1)
+ {
+ nxagentPackQuality = packQuality;
+ }
+
+ /*
+ * Set the minimum size of images being
+ * streamed.
+ */
+
+ if (nxagentSplitThreshold == -1)
+ {
+ nxagentSplitThreshold = splitSize;
+ }
+
+ /*
+ * Let the remote proxy use the shared memory
+ * extension, if supported by the X server.
+ * The client part is not useful and not impl-
+ * emented. The size of the segment is chosen
+ * by the user. The only purpose of the message
+ * is to reserve the XID that will be used by
+ * the remote.
+ */
+
+ enableClient = 0;
+ enableServer = 1;
+
+ if (NXGetShmemParameters(dpy, &enableClient, &enableServer, &clientSegment,
+ &serverSegment, &clientSize, &serverSize) == 0)
+ {
+ fprintf(stderr, "Warning: Failed to get the shared memory parameters.\n");
+ }
+
+ if (enableServer == 1)
+ {
+ fprintf(stderr, "Info: Using shared memory parameters %d/%d/%d/%dK.\n",
+ nxagentOption(SharedMemory), nxagentOption(SharedPixmaps),
+ enableServer, serverSize / 1024);
+ }
+ else
+ {
+ fprintf(stderr, "Info: Using shared memory parameters %d/%d/0/0K.\n",
+ nxagentOption(SharedMemory), nxagentOption(SharedPixmaps));
+ }
+
+ /*
+ * We don't need the NoExpose events. Block
+ * them at the proxy side.
+ */
+
+ NXSetExposeParameters(nxagentDisplay, 1, 1, 0);
+ }
+ else
+ {
+ /*
+ * We don't have a proxy on the remote side.
+ */
+
+ nxagentChangeOption(LinkType, LINK_TYPE_NONE);
+ }
+
+ /*
+ * Set the lossless and lossy pack methods
+ * based on the user's preferences and the
+ * selected link type.
+ */
+
+ nxagentSetPackMethod();
+
+ /*
+ * If not set, set the defer level and the
+ * synchronization timeout based on the link
+ * type.
+ */
+
+ nxagentSetDeferLevel();
+
+ /*
+ * Also set the display output buffer size.
+ */
+
+ nxagentSetBufferSize();
+
+ /*
+ * Select the preferred scheduler.
+ */
+
+ nxagentSetScheduler();
+
+ /*
+ * Select the buffer coalescence timeout.
+ */
+
+ nxagentSetCoalescence();
+
+ /*
+ * Set the other defaults.
+ */
+
+ if (nxagentOption(Fullscreen) == UNDEFINED)
+ {
+ nxagentChangeOption(Fullscreen, False);
+ }
+
+ if (nxagentOption(AllScreens) == UNDEFINED)
+ {
+ nxagentChangeOption(AllScreens, False);
+ }
+
+ if (nxagentOption(Binder) == UNDEFINED)
+ {
+ nxagentChangeOption(Binder, False);
+ }
+
+ if (nxagentOption(Rootless) == UNDEFINED)
+ {
+ nxagentChangeOption(Rootless, False);
+ }
+
+ if (nxagentOption(Desktop) == UNDEFINED)
+ {
+ nxagentChangeOption(Desktop, True);
+ }
+
+ /*
+ * The enableBackingStore flag is defined
+ * in window.c in the dix.
+ */
+/*
+FIXME: In rootless mode the backing-store support is not functional yet.
+*/
+ if (nxagentOption(Rootless))
+ {
+ enableBackingStore = 0;
+ }
+ else if (nxagentOption(BackingStore) == BackingStoreUndefined ||
+ nxagentOption(BackingStore) == BackingStoreForce)
+ {
+ enableBackingStore = 1;
+ }
+ else if (nxagentOption(BackingStore) == BackingStoreNever)
+ {
+ enableBackingStore = 0;
+ }
+
+ /*
+ * need to check if this was set on the
+ * command line as this has the priority
+ * over the option file.
+ */
+
+ if (nxagentRenderEnable == UNDEFINED)
+ {
+ nxagentRenderEnable = True;
+ }
+
+ if (nxagentRenderEnable == True)
+ {
+ nxagentAlphaEnabled = True;
+ }
+ else
+ {
+ nxagentAlphaEnabled = False;
+ }
+
+ if ((nxagentOption(Rootless) == 1) && nxagentOption(Xdmcp))
+ {
+ FatalError("PANIC! Cannot start a XDMCP session in rootless mode.\n");
+ }
+
+ /*
+ * We enable server reset only for indirect
+ * XDMCP sessions.
+ */
+
+ if (nxagentOption(Reset) == True && nxagentMaxAllowedResets == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPostProcessArgs: Disabling the server reset.\n");
+ #endif
+
+ nxagentChangeOption(Reset, False);
+
+ dispatchExceptionAtReset = 0;
+ }
+
+ /*
+ * We skip server reset by default. This should
+ * be equivalent to passing the -noreset option
+ * to a standard XFree86 server.
+ */
+
+ if (nxagentOption(Reset) == False)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPostProcessArgs: Disabling dispatch of exception at server reset.\n");
+ #endif
+
+ dispatchExceptionAtReset = 0;
+ }
+
+ /*
+ * Check if the user activated the auto-disconect
+ * feature.
+ */
+
+ if (nxagentOption(Timeout) > 0)
+ {
+ fprintf(stderr, "Info: Using auto-disconnect timeout of %d seconds.\n",
+ nxagentOption(Timeout));
+
+ nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND;
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentPostProcessArgs: Watchpoint 3.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#16 1 256 bits (0 KB) -> 12 bits (0 KB) -> 256/1 -> 12/1 = 21.333:1
+#233 A 1 256 bits (0 KB) -> 131 bits (0 KB) -> 256/1 -> 131/1 = 1.954:1
+#245 A 2 512 bits (0 KB) -> 19 bits (0 KB) -> 256/1 -> 10/1 = 26.947:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ return useNXTrans;
+}
+
+void ddxUseMsg()
+{
+ ErrorF("-display string display name of the real server\n");
+ ErrorF("-sync synchronize with the real server\n");
+ ErrorF("-full utilize full regeneration\n");
+ ErrorF("-class string default visual class\n");
+ ErrorF("-depth int default depth\n");
+ ErrorF("-geometry WxH+X+Y window size and position\n");
+ ErrorF("-bw int window border width\n");
+ ErrorF("-name string window name\n");
+ ErrorF("-scrns int number of screens to generate\n");
+ ErrorF("-install install colormaps directly\n");
+
+ ErrorF("The NX system adds the following arguments:\n");
+ ErrorF("-forcenx force use of NX protocol messages assuming communication through nxproxy\n");
+ ErrorF("-timeout int auto-disconnect timeout in seconds (minimum allowed: 60)\n");
+ ErrorF("-norootlessexit don't exit if there are no clients in rootless mode\n");
+#ifdef RENDER
+ ErrorF("-norender disable the use of the render extension\n");
+ ErrorF("-nocomposite disable the use of the composite extension\n");
+#endif
+ ErrorF("-nopersistent disable disconnection/reconnection to the X display on SIGHUP\n");
+ ErrorF("-noshmem disable use of shared memory extension\n");
+ ErrorF("-shmem enable use of shared memory extension\n");
+ ErrorF("-noshpix disable use of shared pixmaps\n");
+ ErrorF("-shpix enable use of shared pixmaps\n");
+ ErrorF("-noignore don't ignore pointer and keyboard configuration changes mandated by clients\n");
+ ErrorF("-nokbreset don't reset keyboard device if the session is resumed\n");
+ ErrorF("-noxkblock always allow applications to change layout through XKEYBOARD\n");
+ ErrorF("-tile WxH size of image tiles (minimum allowed: 32x32)\n");
+ ErrorF("-keystrokefile file file with keyboard shortcut definitions\n");
+ ErrorF("-verbose print more warning and error messages\n");
+ ErrorF("-D enable desktop mode\n");
+ ErrorF("-R enable rootless mode\n");
+ ErrorF("-S enable shadow mode\n");
+ ErrorF("-B enable proxy binding mode\n");
+}
+
+static int nxagentGetDialogName()
+{
+ strcpy(nxagentDialogName, "NX");
+
+ *(nxagentDialogName + 255) = '\0';
+
+ if (*nxagentSessionId != '\0')
+ {
+ int length = strlen(nxagentSessionId);
+
+ strcpy(nxagentDialogName, "NX - ");
+
+ if (length > (MD5_LENGTH * 2 + 1) &&
+ *(nxagentSessionId + (length - (MD5_LENGTH * 2 + 1))) == '-')
+ {
+ strncat(nxagentDialogName, nxagentSessionId, length - (MD5_LENGTH * 2 + 1));
+ }
+ else
+ {
+ strncat(nxagentDialogName, nxagentSessionId, 250);
+ }
+
+ *(nxagentSessionId + 255) = '\0';
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void nxagentSetPackMethod(void)
+{
+ unsigned char supportedMethods[NXNumberOfPackMethods];
+ unsigned int entries = NXNumberOfPackMethods;
+
+ int method;
+
+ if (nxagentOption(LinkType) == LINK_TYPE_NONE)
+ {
+ nxagentChangeOption(Streaming, 0);
+
+ nxagentPackMethod = PACK_NONE;
+ nxagentPackLossless = PACK_NONE;
+
+ nxagentSplitThreshold = 0;
+
+ return;
+ }
+
+ /*
+ * Check if we need to select the lossy
+ * and lossless pack methods based on
+ * the link type.
+ */
+
+ method = nxagentPackMethod;
+
+ if (method == PACK_ADAPTIVE)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPackMethod: Using adaptive mode for image compression.\n");
+ #endif
+
+ nxagentChangeOption(Adaptive, 1);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPackMethod: Not using adaptive mode for image compression.\n");
+ #endif
+
+ nxagentChangeOption(Adaptive, 0);
+ }
+
+ if (method == PACK_LOSSY || method == PACK_ADAPTIVE)
+ {
+ nxagentPackMethod = PACK_JPEG_16M_COLORS;
+ }
+ else if (method == PACK_LOSSLESS)
+ {
+ switch (nxagentOption(LinkType))
+ {
+ case LINK_TYPE_MODEM:
+ case LINK_TYPE_ISDN:
+ case LINK_TYPE_ADSL:
+ case LINK_TYPE_WAN:
+ {
+ nxagentPackMethod = PACK_BITMAP_16M_COLORS;
+
+ break;
+ }
+ case LINK_TYPE_LAN:
+ {
+ nxagentPackMethod = PACK_RLE_16M_COLORS;
+
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Warning: Unknown link type '%d' while setting the pack method.\n",
+ nxagentOption(LinkType));
+
+ break;
+ }
+ }
+ }
+
+ /*
+ * Query the remote proxy to determine
+ * whether the selected methods are
+ * supported.
+ */
+
+ if (NXGetUnpackParameters(nxagentDisplay, &entries, supportedMethods) == 0 ||
+ entries != NXNumberOfPackMethods)
+ {
+ fprintf(stderr, "Warning: Unable to retrieve the supported pack methods.\n");
+
+ nxagentPackMethod = PACK_NONE;
+ nxagentPackLossless = PACK_NONE;
+ }
+ else
+ {
+ if (nxagentPackMethod == PACK_BITMAP_16M_COLORS ||
+ nxagentPackMethod == PACK_RLE_16M_COLORS ||
+ nxagentPackMethod == PACK_RGB_16M_COLORS ||
+ nxagentPackMethod == PACK_NONE)
+ {
+ nxagentPackLossless = nxagentPackMethod;
+ }
+ else
+ {
+ if (nxagentOption(LinkType) == LINK_TYPE_LAN)
+ {
+ nxagentPackLossless = PACK_RLE_16M_COLORS;
+ }
+ else
+ {
+ nxagentPackLossless = PACK_BITMAP_16M_COLORS;
+ }
+ }
+
+ if (supportedMethods[nxagentPackLossless] == 0)
+ {
+ nxagentPackLossless = PACK_NONE;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPackMethod: Using method [%d] for lossless compression.\n",
+ nxagentPackLossless);
+ #endif
+
+ if (supportedMethods[nxagentPackMethod] == 0)
+ {
+ fprintf(stderr, "Warning: Pack method '%d' not supported by the proxy.\n",
+ nxagentPackMethod);
+
+ fprintf(stderr, "Warning: Replacing with lossless pack method '%d'.\n",
+ nxagentPackLossless);
+
+ nxagentPackMethod = nxagentPackLossless;
+ }
+ }
+
+ if (nxagentPackMethod == nxagentPackLossless)
+ {
+ nxagentPackQuality = 9;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPackMethod: Assuming pack methods [%d] and [%d] with "
+ "quality [%d].\n", nxagentPackMethod, nxagentPackLossless, nxagentPackQuality);
+ #endif
+}
+
+/*
+ * Each defer level adds the following rules to the previous ones:
+ *
+ * Level 0 Eager encoding.
+ *
+ * Level 1 No data is put or copied on pixmaps, marking them always
+ * as corrupted and synchronizing them on demand, i.e. when
+ * a copy area to a window is requested, the source is syn-
+ * chronized before copying it.
+ *
+ * Level 2 The put images over the windows are skipped marking the
+ * destination as corrupted. The same happens for copy area
+ * and composite operations, spreading the corrupted regions
+ * of involved drawables.
+ */
+
+void nxagentSetDeferLevel()
+{
+ int deferLevel;
+ int tileWidth;
+ int tileHeight;
+ int deferTimeout;
+
+ /*
+ * Streaming is only partly implemented
+ * and is not available in this version
+ * of the agent.
+ */
+
+ if (nxagentOption(Streaming) == 1)
+ {
+ fprintf(stderr, "Warning: Streaming of images not available in this agent.\n");
+
+ nxagentChangeOption(Streaming, 0);
+ }
+
+ switch (nxagentOption(LinkType))
+ {
+ case LINK_TYPE_MODEM:
+ {
+ deferLevel = 2;
+
+ tileWidth = 64;
+ tileHeight = 64;
+
+ deferTimeout = 200;
+
+ break;
+ }
+ case LINK_TYPE_ISDN:
+ {
+ deferLevel = 2;
+
+ tileWidth = 64;
+ tileHeight = 64;
+
+ deferTimeout = 200;
+
+ break;
+ }
+ case LINK_TYPE_ADSL:
+ {
+ deferLevel = 2;
+
+ deferTimeout = 200;
+
+ tileWidth = 4096;
+ tileHeight = 4096;
+
+ break;
+ }
+ case LINK_TYPE_WAN:
+ {
+ deferLevel = 1;
+
+ deferTimeout = 200;
+
+ tileWidth = 4096;
+ tileHeight = 4096;
+
+ break;
+ }
+ case LINK_TYPE_NONE:
+ case LINK_TYPE_LAN:
+ {
+ deferLevel = 0;
+
+ deferTimeout = 200;
+
+ tileWidth = 4096;
+ tileHeight = 4096;
+
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Warning: Unknown link type [%d] processing the defer option.\n",
+ nxagentOption(LinkType));
+
+ deferLevel = 0;
+
+ tileWidth = 64;
+ tileHeight = 64;
+
+ deferTimeout = 200;
+
+ break;
+ }
+ }
+
+ /*
+ * Set the defer timeout.
+ */
+
+ if (nxagentOption(Shadow) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Ignoring defer timeout parameter in shadow mode.\n");
+ #endif
+ }
+ else
+ {
+ nxagentChangeOption(DeferTimeout, deferTimeout);
+ }
+
+ /*
+ * Set the defer level.
+ */
+
+ if (nxagentOption(Shadow) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Ignoring defer parameter in shadow mode.\n");
+ #endif
+ }
+ else if (nxagentOption(DeferLevel) != UNDEFINED)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [defer] option "
+ "with value [%d]. Defer timeout is [%ld] ms.\n", nxagentOption(DeferLevel),
+ nxagentOption(DeferTimeout));
+ #endif
+ }
+ else
+ {
+ nxagentChangeOption(DeferLevel, deferLevel);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Assuming defer level [%d] with timeout of [%ld] ms.\n",
+ nxagentOption(DeferLevel), nxagentOption(DeferTimeout));
+ #endif
+ }
+
+ /*
+ * Set the tile width.
+ */
+
+ if (nxagentOption(TileWidth) != UNDEFINED)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [tile] option "
+ "width value [%d].\n", nxagentOption(TileWidth));
+ #endif
+ }
+ else
+ {
+ nxagentChangeOption(TileWidth, tileWidth);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Assuming tile width [%d].\n",
+ nxagentOption(TileWidth));
+ #endif
+ }
+
+ /*
+ * Set the tile height.
+ */
+
+ if (nxagentOption(TileHeight) != UNDEFINED)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Not overriding the [tile] option "
+ "height value [%d].\n", nxagentOption(TileHeight));
+ #endif
+ }
+ else
+ {
+ nxagentChangeOption(TileHeight, tileHeight);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDeferLevel: Assuming tile height [%d].\n",
+ nxagentOption(TileHeight));
+ #endif
+ }
+}
+
+void nxagentSetBufferSize()
+{
+ int size;
+
+ switch (nxagentOption(LinkType))
+ {
+ case LINK_TYPE_MODEM:
+ {
+ size = 4096;
+
+ break;
+ }
+ case LINK_TYPE_ISDN:
+ {
+ size = 4096;
+
+ break;
+ }
+ case LINK_TYPE_ADSL:
+ {
+ size = 8192;
+
+ break;
+ }
+ case LINK_TYPE_WAN:
+ {
+ size = 16384;
+
+ break;
+ }
+ case LINK_TYPE_NONE:
+ case LINK_TYPE_LAN:
+ {
+ size = 16384;
+
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Warning: Unknown link type '%d' while setting the display buffer size.\n",
+ nxagentOption(LinkType));
+
+ size = 16384;
+
+ break;
+ }
+ }
+
+ nxagentChangeOption(DisplayBuffer, size);
+
+ nxagentBuffer = size;
+
+ if (NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer) < 0)
+ {
+ fprintf(stderr, "Warning: Can't set the display buffer size to [%d].\n",
+ nxagentBuffer);
+ }
+}
+
+void nxagentSetScheduler()
+{
+ /*
+ * The smart scheduler is the default.
+ */
+
+ if (nxagentOption(Shadow) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScheduler: Using the dumb scheduler in shadow mode.\n");
+ #endif
+
+ nxagentDisableTimer();
+ }
+}
+
+void nxagentSetCoalescence()
+{
+ int timeout;
+
+ switch (nxagentOption(LinkType))
+ {
+ case LINK_TYPE_MODEM:
+ {
+ timeout = 50;
+
+ break;
+ }
+ case LINK_TYPE_ISDN:
+ {
+ timeout = 20;
+
+ break;
+ }
+ case LINK_TYPE_ADSL:
+ {
+ timeout = 10;
+
+ break;
+ }
+ case LINK_TYPE_WAN:
+ {
+ timeout = 5;
+
+ break;
+ }
+ case LINK_TYPE_NONE:
+ case LINK_TYPE_LAN:
+ {
+ timeout = 0;
+
+ break;
+ }
+ default:
+ {
+ fprintf(stderr, "Warning: Unknown link type '%d' while setting the display coalescence.\n",
+ nxagentOption(LinkType));
+
+ timeout = 0;
+
+ break;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCoalescence: Using coalescence timeout of [%d] ms.\n",
+ timeout);
+ #endif
+
+ nxagentChangeOption(DisplayCoalescence, timeout);
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Args.h b/nx-X11/programs/Xserver/hw/nxagent/Args.h
new file mode 100644
index 000000000..5192783e5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Args.h
@@ -0,0 +1,97 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Args_H__
+#define __Args_H__
+
+#define MD5_LENGTH 16
+
+struct UserGeometry{
+ int flag;
+ int X;
+ int Y;
+ unsigned int Width;
+ unsigned int Height;
+};
+
+extern Bool nxagentUseNXTrans;
+
+extern char nxagentSessionId[];
+extern char nxagentDisplayName[];
+extern char nxagentShadowDisplayName[];
+extern char nxagentWindowName[];
+extern char nxagentDialogName[];
+
+extern Bool nxagentSynchronize;
+extern Bool nxagentFullGeneration;
+extern int nxagentDefaultClass;
+extern Bool nxagentUserDefaultClass;
+extern int nxagentDefaultDepth;
+extern Bool nxagentUserDefaultDepth;
+extern int nxagentX;
+extern int nxagentY;
+extern unsigned int nxagentWidth;
+extern unsigned int nxagentHeight;
+extern struct UserGeometry nxagentUserGeometry;
+extern Bool nxagentUserBorderWidth;
+extern int nxagentNumScreens;
+extern Bool nxagentDoDirectColormaps;
+extern Window nxagentParentWindow;
+extern int nxagentMaxAllowedReset;
+extern Bool nxagentResizeDesktopAtStartup;
+extern Bool nxagentIpaq;
+
+extern int nxagentLockDeferLevel;
+
+Bool nxagentPostProcessArgs(char *name, Display *dpy, Screen *scr);
+void nxagentProcessOptionsFile(void);
+
+void nxagentSetPackMethod(void);
+void nxagentSetDeferLevel(void);
+void nxagentSetBufferSize(void);
+void nxagentSetScheduler(void);
+void nxagentSetCoalescence(void);
+
+extern int nxagentUserDefinedFontPath;
+
+extern int nxagentRemoteMajor;
+
+extern char *nxagentKeystrokeFile;
+
+#endif /* __Args_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.c b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c
new file mode 100644
index 000000000..0784d6c2c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.c
@@ -0,0 +1,796 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "scrnintstr.h"
+#include "Agent.h"
+
+#include "Xutil.h"
+#include "Xatom.h"
+#include "Xlib.h"
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "resource.h"
+
+#include <nx/NXpack.h>
+
+#include "Atoms.h"
+#include "Args.h"
+#include "Image.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Options.h"
+#include "Agent.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * These values should be moved in
+ * the option repository.
+ */
+
+Bool nxagentWMIsRunning;
+
+static void startWMDetection(void);
+
+static int nxagentInitAtomMap(char **atomNameList, int count, Atom *atomsRet);
+
+#ifdef DEBUG
+static void nxagentPrintAtomMapInfo(char *message);
+#else
+#define nxagentPrintAtomMapInfo(arg)
+#endif
+
+Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS];
+
+static char *nxagentAtomNames[NXAGENT_NUMBER_OF_ATOMS + 1] =
+{
+ "NX_IDENTITY", /* 0 */
+ "WM_PROTOCOLS", /* 1 */
+ "WM_DELETE_WINDOW", /* 2 */
+ "WM_NX_READY", /* 3 */
+ "MCOPGLOBALS", /* 4 */
+ "NX_CUT_BUFFER_SERVER", /* 5 */
+ "TARGETS", /* 6 */
+ "TEXT", /* 7 */
+ "NX_AGENT_SIGNATURE", /* 8 */
+ "NXDARWIN", /* 9 */
+ "CLIPBOARD", /* 10 */
+ "TIMESTAMP", /* 11 */
+ "UTF8_STRING", /* 12 */
+ "_NET_WM_STATE", /* 13 */
+ "_NET_WM_STATE_FULLSCREEN", /* 14 */
+ NULL,
+ NULL
+};
+
+static XErrorHandler previousErrorHandler = NULL;
+
+static void catchAndRedirect(Display* dpy, XErrorEvent* X)
+{
+ if (X -> error_code == BadAccess &&
+ X -> request_code == X_ChangeWindowAttributes &&
+ X -> resourceid == DefaultRootWindow(dpy))
+ {
+ nxagentWMIsRunning = TRUE;
+ }
+ else
+ {
+ previousErrorHandler(dpy, X);
+ }
+}
+
+static void startWMDetection()
+{
+ /*
+ * We are trying to detect if is there any client
+ * that is listening for 'WM' events on the root
+ * window.
+ */
+
+ nxagentWMIsRunning = FALSE;
+
+ previousErrorHandler = XSetErrorHandler((XErrorHandler)&catchAndRedirect);
+
+ /*
+ * After this request we need to Sync with
+ * the X server to be sure we get any error
+ * that is generated.
+ */
+
+ XSelectInput(nxagentDisplay,
+ RootWindow (nxagentDisplay, 0),
+ SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask);
+}
+
+static void finishWMDetection(Bool verbose)
+{
+ XSetErrorHandler(previousErrorHandler);
+
+ if (nxagentWMIsRunning)
+ {
+ if (verbose == 1)
+ {
+ fprintf(stderr, "Info: Detected window manager running.\n");
+ }
+ }
+ else
+ {
+ if (verbose == 1)
+ {
+ fprintf(stderr, "Info: Not found a window manager running.\n");
+ }
+
+ /*
+ * We are not really interested on root window events.
+ */
+
+ XSelectInput(nxagentDisplay, RootWindow (nxagentDisplay, 0), 0);
+ }
+}
+
+void nxagentWMDetect()
+{
+ Bool verbose = False;
+ int windowManagerWasRunning = nxagentWMIsRunning;
+
+ startWMDetection();
+
+ XSync(nxagentDisplay, 0);
+
+ if (windowManagerWasRunning != nxagentWMIsRunning)
+ {
+ verbose = False;
+ }
+
+ finishWMDetection(verbose);
+}
+
+int nxagentInitAtoms(WindowPtr pWin)
+{
+ Atom atom;
+
+ /*
+ * Value of nxagentAtoms[8] is "NX_AGENT_SIGNATURE".
+ *
+ * We don't need to save the atom's value. It will
+ * be checked by other agents to find if they are
+ * run nested.
+ */
+
+ atom = MakeAtom(nxagentAtomNames[8], strlen(nxagentAtomNames[8]), 1);
+
+ if (atom == None)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentInitAtoms: PANIC! Could not create [%s] atom.\n",
+ nxagentAtomNames[8]);
+ #endif
+
+ return -1;
+ }
+
+ return 1;
+}
+
+int nxagentQueryAtoms(ScreenPtr pScreen)
+{
+ int i;
+ static unsigned long atomGeneration = 1;
+
+ int num_of_atoms = NXAGENT_NUMBER_OF_ATOMS;
+ char *names[NXAGENT_NUMBER_OF_ATOMS];
+
+ unsigned long int startingTime = GetTimeInMillis();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentQueryAtoms: Going to create the intern atoms on real display.\n");
+
+ fprintf(stderr, "nxagentQueryAtoms: Starting time is [%ld].\n", startingTime);
+ #endif
+
+ nxagentPrintAtomMapInfo("nxagentQueryAtoms: Entering");
+
+ for (i = 0; i < num_of_atoms; i++)
+ {
+ names[i] = nxagentAtomNames[i];
+
+ nxagentAtoms[i] = None;
+ }
+
+ if (nxagentSessionId[0])
+ {
+ names[num_of_atoms - 1] = nxagentSessionId;
+ }
+ else
+ {
+ num_of_atoms--;
+ }
+
+ startWMDetection();
+
+ nxagentInitAtomMap(names, num_of_atoms, nxagentAtoms);
+
+ /*
+ * We need to be synchronized with the X server
+ * in order to detect the Window Manager, since
+ * after a reset the XInternAtom could be cached
+ * by Xlib.
+ */
+
+ if (atomGeneration != serverGeneration)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentQueryAtoms: The nxagent has been reset with server %ld atom %ld.\n",
+ serverGeneration, atomGeneration);
+
+ fprintf(stderr, "nxagentQueryAtoms: Forcing a sync to detect the window manager.\n");
+ #endif
+
+ atomGeneration = serverGeneration;
+
+ XSync(nxagentDisplay, 0);
+ }
+
+ finishWMDetection(False);
+
+ /*
+ * Value of nxagentAtoms[9] is "NXDARWIN".
+ *
+ * We check if it was created by the NX client.
+ */
+
+ if (nxagentAtoms[9] > nxagentAtoms[0])
+ {
+ nxagentAtoms[9] = None;
+ }
+
+ /*
+ * Value of nxagentAtoms[8] is "NX_AGENT_SIGNATURE".
+ *
+ * This atom is created internally by the agent server at
+ * startup to let other agents determine if they are run
+ * nested. If agent is run nested, in fact, at the time it
+ * will create the NX_AGENT_SIGNATURE atom on the real X
+ * server it will find the existing atom with a value less
+ * than any NX_IDENTITY created but itself.
+ */
+
+ if (nxagentAtoms[8] > nxagentAtoms[0])
+ {
+ nxagentAtoms[8] = None;
+ }
+
+ if (nxagentAtoms[8] != None)
+ {
+ /*
+ * We are running nested in another agent
+ * server.
+ */
+
+ nxagentChangeOption(Nested, 1);
+
+ /*
+ * Avoid the image degradation caused by
+ * multiple lossy encoding.
+ */
+
+ fprintf(stderr, "Warning: Disabling use of lossy encoding in nested mode.\n");
+
+ nxagentPackMethod = nxagentPackLossless;
+ }
+
+ #ifdef TEST
+
+ for (i = 0; i < num_of_atoms; i++)
+ {
+ fprintf(stderr, "nxagentQueryAtoms: Created intern atom [%s] with id [%ld].\n",
+ names[i], nxagentAtoms[i]);
+ }
+
+ #endif
+
+ nxagentChangeOption(DisplayLatency, GetTimeInMillis() - startingTime);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentQueryAtoms: Ending time is [%ld] reference latency is [%d] Ms.\n",
+ GetTimeInMillis(), nxagentOption(DisplayLatency));
+ #endif
+
+ nxagentPrintAtomMapInfo("nxagentQueryAtoms: Exiting");
+
+ return 1;
+}
+
+#define NXAGENT_ATOM_MAP_SIZE_INCREMENT 256
+
+typedef struct {
+ Atom local;
+ Atom remote;
+ const char *string;
+ int length;
+} AtomMap;
+
+static AtomMap *privAtomMap = NULL;
+static unsigned int privAtomMapSize = 0;
+static unsigned int privLastAtom = 0;
+
+static void nxagentExpandCache(void);
+static void nxagentWriteAtom(Atom, Atom, const char*, Bool);
+static AtomMap* nxagentFindAtomByRemoteValue(Atom);
+static AtomMap* nxagentFindAtomByLocalValue(Atom);
+static AtomMap* nxagentFindAtomByName(char*, unsigned);
+
+static void nxagentExpandCache(void)
+{
+ privAtomMapSize += NXAGENT_ATOM_MAP_SIZE_INCREMENT;
+
+ privAtomMap = realloc(privAtomMap, privAtomMapSize * sizeof(AtomMap));
+
+ if (privAtomMap == NULL)
+ {
+ FatalError("nxagentExpandCache: realloc failed\n");
+ }
+}
+
+/*
+ * Check if there is space left on the map
+ * and manage the possible consequent allocation,
+ * then cache the atom-couple.
+ */
+
+static void nxagentWriteAtom(Atom local, Atom remote, const char *string, Bool duplicate)
+{
+ const char *s;
+
+ /*
+ * We could remove this string duplication if
+ * we know for sure that the server will not
+ * reset, since only at reset the dix layer
+ * free all the atom names.
+ */
+
+ if (duplicate)
+ {
+ s = strdup(string);
+
+ #ifdef WARNING
+ if (s == NULL)
+ {
+ fprintf(stderr, "nxagentWriteAtom: Malloc failed.\n");
+ }
+ #endif
+ }
+ else
+ {
+ s = string;
+ }
+
+ if (privLastAtom == privAtomMapSize)
+ {
+ nxagentExpandCache();
+ }
+
+ privAtomMap[privLastAtom].local = local;
+ privAtomMap[privLastAtom].remote = remote;
+ privAtomMap[privLastAtom].string = s;
+ privAtomMap[privLastAtom].length = strlen(s);
+
+ privLastAtom++;
+}
+
+/*
+ * FIXME: We should clean up the atom map
+ * at nxagent reset, in order to cancel
+ * all the local atoms but still mantaining
+ * the Xserver values and the atom names.
+ */
+
+void nxagentResetAtomMap()
+{
+ unsigned i;
+
+ nxagentPrintAtomMapInfo("nxagentResetAtomMap: Entering");
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ privAtomMap[i].local = None;
+ }
+
+ nxagentPrintAtomMapInfo("nxagentResetAtomMap: Exiting");
+}
+
+/*
+ * Init map.
+ * Initializing the atomNameList all in one.
+ */
+
+static int nxagentInitAtomMap(char **atomNameList, int count, Atom *atomsRet)
+{
+ XlibAtom *atom_list;
+ char **name_list;
+ unsigned int i;
+ int ret_value = 0;
+ int list_size = count + privLastAtom;
+
+ nxagentPrintAtomMapInfo("nxagentInitAtomMap: Entering");
+
+ atom_list = malloc((list_size) * sizeof(*atom_list));
+ name_list = malloc((list_size) * sizeof(char*));
+
+ if ((atom_list == NULL) || (name_list == NULL))
+ {
+ FatalError("nxagentInitAtomMap: malloc failed\n");
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ name_list[i] = atomNameList[i];
+ atom_list[i] = None;
+ }
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ name_list[count + i] = (char *)privAtomMap[i].string;
+ atom_list[count + i] = None;
+ }
+
+ /*
+ * Ask X-Server for ours Atoms
+ * ... if successfull cache them too.
+ */
+
+ ret_value = XInternAtoms(nxagentDisplay, name_list, list_size, False, atom_list);
+
+ if (ret_value == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitAtomMap: WARNING! XInternAtoms request failed.\n");
+ #endif
+
+ free(atom_list);
+ free(name_list);
+
+ return 0;
+ }
+
+ for (i = 0; i < list_size; i++)
+ {
+ AtomMap *aMap = nxagentFindAtomByName(name_list[i], strlen(name_list[i]));
+
+ if (aMap == NULL)
+ {
+ Atom local = MakeAtom(name_list[i], strlen(name_list[i]), True);
+
+ if (ValidAtom(local))
+ {
+ nxagentWriteAtom(local, atom_list[i], name_list[i], False);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitAtomMap: WARNING MakeAtom failed.\n");
+ #endif
+ }
+ }
+ else
+ {
+ aMap -> remote = atom_list[i];
+
+ if (i < count && aMap -> local == None)
+ {
+ aMap -> local = MakeAtom(name_list[i], strlen(name_list[i]), True);
+ }
+ }
+
+ if (i < count)
+ {
+ atomsRet[i] = atom_list[i];
+ }
+ }
+
+ free(atom_list);
+ free(name_list);
+
+ nxagentPrintAtomMapInfo("nxagentInitAtomMap: Exiting");
+
+ return 1;
+}
+
+/*
+ * If the nxagent has been resetted,
+ * the local value of the atoms stored
+ * in cache could have the value None,
+ * do not call this function with None.
+ */
+
+static AtomMap* nxagentFindAtomByLocalValue(Atom local)
+{
+ unsigned i;
+
+ if (!ValidAtom(local))
+ {
+ return NULL;
+ }
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ if (local == privAtomMap[i].local)
+ {
+ return (privAtomMap + i);
+ }
+ }
+
+ return NULL;
+}
+
+static AtomMap* nxagentFindAtomByRemoteValue(Atom remote)
+{
+ unsigned i;
+
+ if (remote == None || remote == BAD_RESOURCE)
+ {
+ return NULL;
+ }
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ if (remote == privAtomMap[i].remote)
+ {
+ return (privAtomMap + i);
+ }
+ }
+
+ return NULL;
+}
+
+static AtomMap* nxagentFindAtomByName(char *string, unsigned int length)
+{
+ unsigned i;
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ if ((length == privAtomMap[i].length) &&
+ (strcmp(string, privAtomMap[i].string) == 0))
+ {
+ return (privAtomMap + i);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Convert local atom's name to X-server value.
+ * Reading them from map, if they have been already cached or
+ * really asking to X-server and caching them.
+ * FIXME: I don't really know if is better to allocate
+ * an automatic variable like ret_value and write it, instead of make all
+ * these return!, perhaps this way the code is a little bit easyer to read.
+ * I think this and the 2 .*Find.* are the only functions to look for performances.
+ */
+
+Atom nxagentMakeAtom(char *string, unsigned int length, Bool Makeit)
+{
+ Atom local;
+ AtomMap *current;
+
+ /*
+ * Surely MakeAtom is faster than
+ * our nxagentFindAtomByName.
+ */
+
+ local = MakeAtom(string, length, Makeit);
+
+ if (!ValidAtom(local))
+ {
+ return None;
+ }
+
+ if (local <= XA_LAST_PREDEFINED)
+ {
+ return local;
+ }
+
+ if ((current = nxagentFindAtomByLocalValue(local)))
+ {
+ /*
+ * Found cached by value.
+ */
+
+ return current->remote;
+ }
+
+ if ((current = nxagentFindAtomByName(string, length)))
+ {
+ /*
+ * Found Cached by name.
+ * It means that nxagent has been resetted,
+ * but not the xserver so we still have cached its atoms.
+ */
+
+ current->local = local;
+
+ return current->remote;
+ }
+
+ /*
+ * We really have to ask Xserver for it.
+ */
+
+ {
+ Atom remote;
+
+ remote = XInternAtom(nxagentDisplay, string, !Makeit);
+
+ if (remote == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentMakeAtom: WARNING XInternAtom failed.\n");
+ #endif
+
+ return None;
+ }
+
+ nxagentWriteAtom(local, remote, string, True);
+
+ return remote;
+ }
+}
+
+Atom nxagentLocalToRemoteAtom(Atom local)
+{
+ AtomMap *current;
+ const char *string;
+ Atom remote;
+
+ if (!ValidAtom(local))
+ {
+ return None;
+ }
+
+ if (local <= XA_LAST_PREDEFINED)
+ {
+ return local;
+ }
+
+ if ((current = nxagentFindAtomByLocalValue(local)))
+ {
+ return current->remote;
+ }
+
+ string = NameForAtom(local);
+
+ remote = XInternAtom(nxagentDisplay, string, False);
+
+ if (remote == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentLocalToRemoteAtom: WARNING XInternAtom failed.\n");
+ #endif
+
+ return None;
+ }
+
+ nxagentWriteAtom(local, remote, string, True);
+
+ return remote;
+}
+
+Atom nxagentRemoteToLocalAtom(Atom remote)
+{
+ AtomMap *current;
+ char *string;
+ Atom local;
+
+ if (remote == None || remote == BAD_RESOURCE)
+ {
+ return None;
+ }
+
+ if (remote <= XA_LAST_PREDEFINED)
+ {
+ return remote;
+ }
+
+ if ((current = nxagentFindAtomByRemoteValue(remote)))
+ {
+ if (!ValidAtom(current->local))
+ {
+ local = MakeAtom(current->string, current->length, True);
+
+ if (ValidAtom(local))
+ {
+ current->local = local;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING MakeAtom failed.\n");
+ #endif
+
+ current->local = None;
+ }
+ }
+
+ return current->local;
+ }
+
+ if ((string = XGetAtomName(nxagentDisplay, remote)))
+ {
+ local = MakeAtom(string, strlen(string), True);
+
+ if (!ValidAtom(local))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING MakeAtom failed.\n");
+ #endif
+
+ local = None;
+ }
+
+ nxagentWriteAtom(local, remote, string, True);
+
+ XFree(string);
+
+ return local;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRemoteToLocalAtom: WARNING failed to get name from remote atom.\n");
+ #endif
+
+ return None;
+}
+
+#ifdef DEBUG
+
+static void nxagentPrintAtomMapInfo(char *message)
+{
+ unsigned i;
+
+ fprintf(stderr, "--------------- Atom map in context [%s] ----------------------\n", message);
+ fprintf(stderr, "nxagentPrintAtomMapInfo: Map at [%p] size [%d] number of entry [%d] auto increment [%d].\n",
+ (void*) privAtomMap, privLastAtom, privAtomMapSize, NXAGENT_ATOM_MAP_SIZE_INCREMENT);
+
+ for (i = 0; i < privLastAtom; i++)
+ {
+ fprintf(stderr, "[%5.1d] local: %6.1lu - remote: %6.1lu - [%p] %s\n", i,
+ privAtomMap[i].local,
+ privAtomMap[i].remote,
+ privAtomMap[i].string, validateString(privAtomMap[i].string));
+ }
+
+ fprintf(stderr, "---------------------------------------------\n");
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Atoms.h b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h
new file mode 100644
index 000000000..391e06181
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Atoms.h
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Atoms_H__
+#define __Atoms_H__
+
+#include "X.h"
+#include "../../include/window.h"
+#include "screenint.h"
+
+#define NXAGENT_NUMBER_OF_ATOMS 16
+
+extern Atom nxagentAtoms[NXAGENT_NUMBER_OF_ATOMS];
+
+extern Bool nxagentWMIsRunning;
+
+/*
+ * Create the required atoms internally
+ * to the agent server.
+ */
+
+int nxagentInitAtoms(WindowPtr pWin);
+
+/*
+ * Query and create all the required atoms
+ * on the remote X server using a single
+ * round trip.
+ */
+
+int nxagentQueryAtoms(ScreenPtr pScreen);
+
+/*
+ * Create the atoms on the remote X server
+ * and cache the couple local-remote atoms.
+ */
+
+Atom nxagentMakeAtom(char *, unsigned, Bool);
+
+/*
+ * Converts local atoms in remote atoms and
+ * viceversa.
+ */
+
+Atom nxagentRemoteToLocalAtom(Atom);
+Atom nxagentLocalToRemoteAtom(Atom);
+
+void nxagentResetAtomMap(void);
+
+void nxagentWMDetect(void);
+
+#endif /* __Atoms_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Binder.c b/nx-X11/programs/Xserver/hw/nxagent/Binder.c
new file mode 100644
index 000000000..ae1cd0f25
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.c
@@ -0,0 +1,185 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <nx/NX.h>
+
+#include "Binder.h"
+#include "Options.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+int nxagentCheckBinder(int argc, char *argv[], int i)
+{
+ if (++i < argc)
+ {
+ char *display;
+ char *found;
+
+ int port;
+
+ display = argv[i];
+
+ /*
+ * Check if a display specification follows
+ * the -B switch.
+ */
+
+ found = rindex(display, ':');
+
+ if (found == NULL || *(found + 1) == '\0' ||
+ isdigit(*(found + 1)) == 0)
+ {
+ fprintf(stderr, "Error: Can't identify the display port in string '%s'.\n",
+ display);
+
+ return 0;
+ }
+
+ port = atoi(found + 1);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckBinder: Identified agent display port [%d].\n",
+ port);
+ #endif
+
+ /*
+ * The NX options must be specified in the DISPLAY
+ * environment. Check if the display specified on
+ * the command line matches the NX virtual display.
+ */
+
+ display = getenv("DISPLAY");
+
+ if (display == NULL || *display == '\0')
+ {
+ fprintf(stderr, "Error: No DISPLAY environment found.\n");
+
+ return 0;
+ }
+
+ found = rindex(display, ':');
+
+ if (found == NULL || *(found + 1) == '\0' ||
+ isdigit(*(found + 1)) == 0 || atoi(found + 1) != port)
+ {
+ fprintf(stderr, "Error: The NX display doesn't match the agent display :%d.\n",
+ port);
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckBinder: Identified NX display port [%d].\n",
+ atoi(found + 1));
+ #endif
+
+ /*
+ * Save the proxy options. They will be later
+ * used to create the transport.
+ */
+
+ nxagentChangeOption(Rootless, False);
+ nxagentChangeOption(Desktop, False);
+ nxagentChangeOption(Binder, True);
+
+ /*
+ * FIXME: This now points to the buffer that was
+ * returned by getenv(). It is to be decided how
+ * to handle the values of type string in the
+ * Options repository.
+ */
+
+ nxagentChangeOption(BinderOptions, display);
+
+ return 2;
+ }
+
+ fprintf(stderr, "Error: No display port specified in command.\n");
+
+ return 0;
+}
+
+int nxagentBinderLoop()
+{
+ struct timeval timeout;
+
+ char *options = nxagentOption(BinderOptions);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBinderLoop: Creating the NX transport.\n");
+ #endif
+
+ if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, options) < 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBinderLoop: PANIC! Error creating the NX transport.\n");
+ #endif
+
+ return -1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBinderLoop: Yielding control to the NX entry point.\n");
+ #endif
+
+ while (NXTransRunning(NX_FD_ANY))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBinderLoop: Going to run a new NX proxy loop.\n");
+ #endif
+
+ timeout.tv_sec = 10;
+ timeout.tv_usec = 0;
+
+ NXTransContinue(&timeout);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBinderLoop: Completed execution of the NX loop.\n");
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBinderLoop: Exiting the NX proxy binder loop.\n");
+ #endif
+
+ return 1;
+}
+
+void nxagentBinderExit(int code)
+{
+ NXTransExit(code);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Binder.h b/nx-X11/programs/Xserver/hw/nxagent/Binder.h
new file mode 100644
index 000000000..fc6673132
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Binder.h
@@ -0,0 +1,35 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Binder_H__
+#define __Binder_H__
+
+int nxagentCheckBinder(int argc, char *argv[], int i);
+
+int nxagentBinderLoop(void);
+
+void nxagentBinderExit(int code);
+
+#endif /* __Binder_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/BitmapUtils.c b/nx-X11/programs/Xserver/hw/nxagent/BitmapUtils.c
new file mode 100644
index 000000000..b889d2a62
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/BitmapUtils.c
@@ -0,0 +1,118 @@
+/*
+
+Copyright 1990, 1994, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+/*
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/*
+ * Derived from libXfont1's utilbitmap.c (available via fontmisc.h).
+ */
+
+/* Utility functions for reformating font bitmaps */
+
+static const unsigned char _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+/*
+ * Invert bit order within each BYTE of an array.
+ */
+void
+nxagentBitOrderInvert(unsigned char *buf, int nbytes)
+{
+ const unsigned char *rev = _reverse_byte;
+
+ for (; --nbytes >= 0; buf++)
+ *buf = rev[*buf];
+}
+
+/*
+ * Invert byte order within each 16-bits of an array.
+ */
+void
+nxagentTwoByteSwap(unsigned char *buf, int nbytes)
+{
+ unsigned char c;
+
+ for (; nbytes > 0; nbytes -= 2, buf += 2)
+ {
+ c = buf[0];
+ buf[0] = buf[1];
+ buf[1] = c;
+ }
+}
+
+/*
+ * Invert byte order within each 32-bits of an array.
+ */
+void
+nxagentFourByteSwap(unsigned char *buf, int nbytes)
+{
+ unsigned char c;
+
+ for (; nbytes > 0; nbytes -= 4, buf += 4)
+ {
+ c = buf[0];
+ buf[0] = buf[3];
+ buf[3] = c;
+ c = buf[1];
+ buf[1] = buf[2];
+ buf[2] = c;
+ }
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Client.c b/nx-X11/programs/Xserver/hw/nxagent/Client.c
new file mode 100644
index 000000000..38d877ed7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Client.c
@@ -0,0 +1,546 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Used in handling of karma on lost focus.
+ */
+
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+
+#include <nx/NX.h>
+
+#include "Xatom.h"
+#include "dixstruct.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "osdep.h"
+
+/*
+ * NX specific includes and definitions.
+ */
+
+#include "Agent.h"
+#include "Args.h"
+#include "Display.h"
+#include "Client.h"
+#include "Dialog.h"
+#include "Handlers.h"
+#include "Events.h"
+#include "Drawable.h"
+#include "Utils.h"
+
+/*
+ * Need to include this after the stub
+ * definition of GC in Agent.h.
+ */
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Returns the last signal delivered
+ * to the process.
+ */
+
+extern int _X11TransSocketCheckSignal(void);
+
+/*
+ * Time in milliseconds of first iteration
+ * through the dispatcher.
+ */
+
+unsigned long nxagentStartTime = -1;
+
+/*
+ * If defined, add a function checking if we
+ * need a null timeout after a client wakeup.
+ */
+
+#undef CHECK_RESTARTED_CLIENTS
+
+#ifdef CHECK_RESTARTED_CLIENTS
+
+void nxagentCheckRestartedClients(struct timeval **timeout);
+
+#endif
+
+/*
+ * Allow attaching private members to the client.
+ */
+
+int nxagentClientPrivateIndex;
+
+/*
+ * The master nxagent holds in nxagentShadowCounter
+ * the number of shadow nxagents connected to itself.
+ */
+
+int nxagentShadowCounter = 0;
+
+void nxagentInitClientPrivates(ClientPtr client)
+{
+ if (nxagentClientPriv(client))
+ {
+ nxagentClientPriv(client) -> clientState = 0;
+ nxagentClientPriv(client) -> clientBytes = 0;
+ nxagentClientPriv(client) -> clientHint = UNKNOWN;
+ }
+}
+
+/*
+ * Guess the running application based on the
+ * properties attached to its main window.
+ */
+
+void nxagentGuessClientHint(ClientPtr client, Atom property, char *data)
+{
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentGuessClientHint: Client [%d] setting property [%s] as [%s].\n",
+ client -> index, validateString(NameForAtom(property)), validateString(data));
+ #endif
+
+ if (nxagentClientPriv(client) -> clientHint == UNKNOWN)
+ {
+ if (property == XA_WM_CLASS)
+ {
+ if (strcmp(data, "nxclient") == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentGuessClientHint: Detected nxclient as [%d].\n", client -> index);
+ #endif
+
+ nxagentClientHint(client) = NXCLIENT_WINDOW;
+ }
+ else if (strstr(data, "java"))
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentGuessClientHint: Detected java as [%d].\n", client -> index);
+ #endif
+
+ nxagentClientHint(client) = JAVA_WINDOW;
+ }
+ }
+ }
+
+ if (nxagentClientPriv(client) -> clientHint == NXCLIENT_WINDOW)
+ {
+ if (property == MakeAtom("WM_WINDOW_ROLE", 14, True) &&
+ strncmp(data, "msgBox", 6) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentGuessClientHint: Detected nxclient dialog as [%d].\n", client -> index);
+ #endif
+
+ nxagentClientHint(client) = NXCLIENT_DIALOG;
+ }
+ }
+}
+
+void nxagentGuessShadowHint(ClientPtr client, Atom property)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGuessShadowHint: Client [%d] setting property [%s].\n",
+ client -> index,
+ validateString(NameForAtom(property)));
+ #endif
+
+ if (nxagentClientPriv(client) -> clientHint == UNKNOWN)
+ {
+ if (strcmp(validateString(NameForAtom(property)), "_NX_SHADOW") == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGuessShadowHint: nxagentShadowCounter [%d].\n",
+ nxagentShadowCounter);
+
+ fprintf(stderr, "nxagentGuessShadowHint: Detected shadow nxagent as client [%d].\n",
+ client -> index);
+
+ #endif
+
+ nxagentClientHint(client) = NXAGENT_SHADOW;
+
+ nxagentShadowCounter++;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGuessShadowHint: nxagentShadowCounter [%d].\n",
+ nxagentShadowCounter);
+ #endif
+
+ /*
+ * From this moment on we ignore the visibility
+ * checks to keep the windows updated.
+ */
+
+ nxagentChangeOption(IgnoreVisibility, 1);
+ }
+ }
+}
+
+void nxagentCheckIfShadowAgent(ClientPtr client)
+{
+
+ if (nxagentClientPriv(client) -> clientHint == NXAGENT_SHADOW)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckIfShadowAgent: nxagentShadowCounter [%d].\n",
+ nxagentShadowCounter);
+
+ fprintf(stderr, "nxagentCheckIfShadowAgent: Shadow nxagent as client [%d] detached.\n",
+ client -> index);
+
+ fprintf(stderr, "nxagentCheckIfShadowAgent: Decreasing nxagentShadowCounter.\n");
+ #endif
+
+ /*
+ * We decrease nxagentShadowCounter.
+ */
+
+ nxagentShadowCounter--;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckIfShadowAgent: nxagentShadowCounter [%d].\n",
+ nxagentShadowCounter);
+ #endif
+
+
+ if (nxagentShadowCounter == 0)
+ {
+ /*
+ * The last shadow nxagent has been detached
+ * from master nxagent.
+ * The master nxagent could do some action
+ * here.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckIfShadowAgent: The last shadow nxagent has been detached.\n");
+ #endif
+
+ nxagentChangeOption(IgnoreVisibility, 0);
+ }
+ }
+}
+
+void nxagentWakeupByReconnect()
+{
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWakeupByReconnect: Going to wakeup all clients.\n");
+ #endif
+
+ for (i = 1; i < currentMaxClients; i++)
+ {
+ if (clients[i] != NULL)
+ {
+ nxagentWakeupByReset(clients[i]);
+ }
+ }
+}
+
+void nxagentWakeupByReset(ClientPtr client)
+{
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWakeupByReset: Going to check client id [%d].\n",
+ client -> index);
+ #endif
+
+ if (nxagentNeedWakeup(client))
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWakeupByReset: Going to wakeup client id [%d].\n",
+ client -> index);
+ #endif
+
+ if (client -> index < MAX_CONNECTIONS)
+ {
+ if (nxagentNeedWakeupBySplit(client))
+ {
+ nxagentWakeupBySplit(client);
+ }
+ }
+ }
+
+ if (client -> index < MAX_CONNECTIONS)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWakeupByReset: Going to reset bytes received for client id [%d].\n",
+ client -> index);
+ #endif
+
+ nxagentClientBytes(client) = 0;
+ }
+}
+
+/*
+ * Wait for any event.
+ */
+
+#define WAIT_ALL_EVENTS
+
+#ifndef WAIT_ALL_EVENTS
+
+static Bool nxagentWaitWakeupBySplitPredicate(Display *display, XEvent *event, XPointer ptr)
+{
+ return (event -> type == ClientMessage &&
+ (event -> xclient.data.l[0] == NXNoSplitNotify ||
+ event -> xclient.data.l[0] == NXStartSplitNotify ||
+ event -> xclient.data.l[0] == NXCommitSplitNotify ||
+ event -> xclient.data.l[0] == NXEndSplitNotify ||
+ event -> xclient.data.l[0] == NXEmptySplitNotify) &&
+ event -> xclient.window == 0 && event -> xclient.message_type == 0 &&
+ event -> xclient.format == 32);
+}
+
+#endif
+
+#define USE_FINISH_SPLIT
+
+void nxagentWaitWakeupBySplit(ClientPtr client)
+{
+ #ifdef TEST
+
+ if (nxagentNeedWakeupBySplit(client) == 0)
+ {
+ fprintf(stderr, "++++++nxagentWaitWakeupBySplit: WARNING! The client [%d] is already awake.\n",
+ client -> index);
+ }
+
+ fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Going to wait for the client [%d].\n",
+ client -> index);
+ #endif
+
+ /*
+ * Be sure we intercept an I/O error
+ * as well as an interrupt.
+ */
+
+ #ifdef USE_FINISH_SPLIT
+
+ NXFinishSplit(nxagentDisplay, client -> index);
+
+ #endif
+
+ NXFlushDisplay(nxagentDisplay, NXFlushBuffer);
+
+ for (;;)
+ {
+ /*
+ * Can we handle all the possible events here
+ * or we need to select only the split events?
+ * Handling all the possible events would pre-
+ * empt the queue and make a better use of the
+ * link.
+ */
+
+ #ifdef WAIT_ALL_EVENTS
+
+ nxagentDispatchEvents(NULL);
+
+ #else
+
+ nxagentDispatchEvents(nxagentWaitWakeupBySplitPredicate);
+
+ #endif
+
+ if (nxagentNeedWakeupBySplit(client) == 0 ||
+ NXDisplayError(nxagentDisplay) == 1)
+ {
+ #ifdef TEST
+
+ if (nxagentNeedWakeupBySplit(client) == 0)
+ {
+ fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Client [%d] can now run.\n",
+ client -> index);
+ }
+ else
+ {
+ fprintf(stderr, "++++++nxagentWaitWakeupBySplit: WARNING! Display error "
+ "detected waiting for restart.\n");
+ }
+
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWaitWakeupBySplit: Yielding control to the NX transport.\n");
+ #endif
+
+ nxagentWaitEvents(nxagentDisplay, NULL);
+ }
+}
+
+int nxagentSuspendBySplit(ClientPtr client)
+{
+/*
+FIXME: Should record a serial number for the client, so that
+ the client is not restarted because of an end of split
+ of a previous client with the same index.
+*/
+ if (client -> index < MAX_CONNECTIONS)
+ {
+ if (nxagentNeedWakeup(client) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentSuspendBySplit: Suspending client [%d] with agent sequence [%ld].\n",
+ client -> index, NextRequest(nxagentDisplay) - 1);
+ #endif
+
+ if (client -> clientGone == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentSuspendBySplit: Client [%d] suspended.\n", client -> index);
+ #endif
+
+ IgnoreClient(client);
+ }
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "++++++nxagentSuspendBySplit: WARNING! Client [%d] already ignored with state [%x].\n",
+ client -> index, nxagentClientPriv(client) -> clientState);
+ }
+ #endif
+
+ nxagentClientPriv(client) -> clientState |= SleepingBySplit;
+
+ return 1;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "++++++nxagentSuspendBySplit: WARNING! Invalid client [%d] provided to function.\n",
+ client -> index);
+ #endif
+
+ return -1;
+}
+
+int nxagentWakeupBySplit(ClientPtr client)
+{
+/*
+FIXME: Should record a serial number for the client, so that
+ the client is not restarted because of the end of the
+ split for a previous client with the same index.
+*/
+ if (client -> index < MAX_CONNECTIONS)
+ {
+ nxagentClientPriv(client) -> clientState &= ~SleepingBySplit;
+
+ if (nxagentNeedWakeup(client) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWakeupBySplit: Resuming client [%d] with agent sequence [%ld].\n",
+ client -> index, NextRequest(nxagentDisplay) - 1);
+ #endif
+
+ if (client -> clientGone == 0)
+ {
+ AttendClient(client);
+ }
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "++++++nxagentWakeupBySplit: WARNING! Client [%d] still suspended with state [%x].\n",
+ client -> index, nxagentClientPriv(client) -> clientState);
+ }
+ #endif
+
+ return 1;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "++++++nxagentWakeupBySplit: WARNING! Invalid client [%d] provided to function.\n",
+ client -> index);
+ #endif
+
+ return -1;
+}
+
+#ifdef CHECK_RESTARTED_CLIENTS
+
+void nxagentCheckRestartedClients(struct timeval **timeout)
+{
+ static struct timeval zero;
+
+ int i;
+
+ /*
+ * If any of the restarted clients had requests
+ * in input we'll need to enter the select with
+ * a null timeout, or we will block until any
+ * other client becomes available.
+ */
+
+ for (i = 1; i < currentMaxClients; i++)
+ {
+ if (clients[i] != NULL && clients[i] -> osPrivate != NULL &&
+ nxagentNeedWakeup(clients[i]) == 0)
+ {
+ int fd = ((OsCommPtr) clients[i] -> osPrivate) -> fd;
+
+ if (FD_ISSET(fd, &ClientsWithInput))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentBlockHandler: WARNING! Client [%d] with fd [%d] has input.\n",
+ clients[i] -> index, fd);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBlockHandler: Setting a null timeout with former timeout [%ld] Ms.\n",
+ (*timeout) -> tv_sec * 1000 + (*timeout) -> tv_usec / 1000);
+ #endif
+
+ if (*timeout != NULL)
+ {
+ (*timeout) -> tv_sec = 0;
+ (*timeout) -> tv_usec = 0;
+ }
+ else
+ {
+ zero.tv_sec = 0;
+ zero.tv_usec = 0;
+
+ *timeout = &zero;
+ }
+ }
+ }
+ }
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Client.h b/nx-X11/programs/Xserver/hw/nxagent/Client.h
new file mode 100644
index 000000000..8f4f503ba
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Client.h
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Client_H__
+#define __Client_H__
+
+#define MAX_CONNECTIONS 256
+
+/*
+ * The master nxagent holds in nxagentShadowCounter
+ * the number of shadow nxagents connected to itself.
+ */
+
+extern int nxagentShadowCounter;
+
+enum ClientHint
+{
+ UNKNOWN = 0,
+ NXCLIENT_WINDOW,
+ NXCLIENT_DIALOG,
+ NXAGENT_SHADOW,
+ JAVA_WINDOW
+};
+
+typedef struct _PrivClientRec
+{
+ int clientState;
+ long clientBytes;
+ enum ClientHint clientHint;
+
+} PrivClientRec;
+
+extern int nxagentClientPrivateIndex;
+
+#define nxagentClientPriv(pClient) \
+ ((PrivClientRec *)((pClient)->devPrivates[nxagentClientPrivateIndex].ptr))
+
+void nxagentInitClientPrivates(ClientPtr);
+
+#define nxagentClientAddBytes(pClient, size) \
+ (nxagentClientPriv(pClient) -> clientBytes += (size))
+
+#define nxagentClientBytes(pClient) \
+ (nxagentClientPriv(pClient) -> clientBytes)
+
+#define nxagentClientHint(pClient) \
+ (nxagentClientPriv(pClient) -> clientHint)
+
+#define nxagentClientIsDialog(pClient) \
+ (nxagentClientHint(pClient) == NXCLIENT_DIALOG)
+
+/*
+ * The actual reason why the client
+ * is sleeping.
+ */
+
+#define SleepingBySplit 1
+
+#define nxagentNeedWakeup(client) \
+ ((nxagentClientPriv(client) -> \
+ clientState) != 0)
+
+#define nxagentNeedWakeupBySplit(client) \
+ (((nxagentClientPriv(client) -> \
+ clientState) & SleepingBySplit) != 0)
+
+void nxagentGuessClientHint(ClientPtr, Atom, char*);
+
+void nxagentGuessShadowHint(ClientPtr, Atom);
+
+void nxagentCheckIfShadowAgent(ClientPtr);
+
+/*
+ * Suspend or restart the agent's
+ * client.
+ */
+
+int nxagentSuspendBySplit(ClientPtr client);
+int nxagentWakeupBySplit(ClientPtr client);
+
+/*
+ * Wait until the given client is
+ * restarted.
+ */
+
+void nxagentWaitWakeupBySplit(ClientPtr client);
+
+/*
+FIXME: This must be moved to Drawable.h.
+*/
+void nxagentWaitDrawable(DrawablePtr pDrawable);
+
+/*
+ * Wakeup all the sleeping clients.
+ */
+
+void nxagentWakeupByReconnect(void);
+
+/*
+ * Reset the client state before
+ * closing it down.
+ */
+
+void nxagentWakeupByReset(ClientPtr client);
+
+#endif /* __Client_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
new file mode 100644
index 000000000..d26d3524a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.c
@@ -0,0 +1,1677 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "X.h"
+#include "Xproto.h"
+#include "Xatom.h"
+#include "selection.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+
+#include "Windows.h"
+#include "Atoms.h"
+#include "Agent.h"
+#include "Args.h"
+#include "Trap.h"
+#include "Rootless.h"
+#include "Clipboard.h"
+
+#include "gcstruct.h"
+#include "xfixeswire.h"
+#include "X11/include/Xfixes_nxagent.h"
+
+/*
+ * Use asyncronous get property replies.
+ */
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * These are defined in the dispatcher.
+ */
+
+extern int NumCurrentSelections;
+extern Selection *CurrentSelections;
+
+int nxagentLastClipboardClient = -1;
+
+static int agentClipboardStatus;
+static int clientAccum;
+
+Atom serverCutProperty;
+Atom clientCutProperty;
+static Window serverWindow;
+
+static const int nxagentPrimarySelection = 0;
+static const int nxagentClipboardSelection = 1;
+static const int nxagentMaxSelections = 2;
+
+typedef struct _SelectionOwner
+{
+ Atom selection;
+ ClientPtr client;
+ Window window;
+ WindowPtr windowPtr;
+ Time lastTimeChanged;
+
+} SelectionOwner;
+
+static SelectionOwner *lastSelectionOwner;
+static Atom nxagentLastRequestedSelection;
+static Atom nxagentClipboardAtom;
+static Atom nxagentTimestampAtom;
+
+/*
+ * Needed to handle the notify selection event to
+ * be sent to client once the selection property
+ * has been retrieved from the real X server.
+ */
+
+typedef enum
+{
+ SelectionStageNone,
+ SelectionStageQuerySize,
+ SelectionStageWaitSize,
+ SelectionStageQueryData,
+ SelectionStageWaitData
+} ClientSelectionStage;
+
+static WindowPtr lastClientWindowPtr;
+static ClientPtr lastClientClientPtr;
+static Window lastClientRequestor;
+static Atom lastClientProperty;
+static Atom lastClientSelection;
+static Atom lastClientTarget;
+static Time lastClientTime;
+static Time lastClientReqTime;
+static unsigned long lastClientPropertySize;
+
+static ClientSelectionStage lastClientStage;
+
+static Window lastServerRequestor;
+static Atom lastServerProperty;
+static Atom lastServerTarget;
+static Time lastServerTime;
+
+static Atom serverTARGETS;
+static Atom serverTEXT;
+static Atom serverUTF8_STRING;
+static Atom clientTARGETS;
+static Atom clientTEXT;
+static Atom clientCOMPOUND_TEXT;
+static Atom clientUTF8_STRING;
+
+static char szAgentTARGETS[] = "TARGETS";
+static char szAgentTEXT[] = "TEXT";
+static char szAgentCOMPOUND_TEXT[] = "COMPOUND_TEXT";
+static char szAgentUTF8_STRING[] = "UTF8_STRING";
+static char szAgentNX_CUT_BUFFER_CLIENT[] = "NX_CUT_BUFFER_CLIENT";
+
+/*
+ * Save the values queried from X server.
+ */
+
+XFixesAgentInfoRec nxagentXFixesInfo = { -1, -1, -1, 0 };
+
+extern Display *nxagentDisplay;
+
+Bool nxagentValidServerTargets(Atom target);
+void nxagentSendSelectionNotify(Atom property);
+void nxagentTransferSelection(int resource);
+void nxagentCollectPropertyEvent(int resource);
+void nxagentResetSelectionOwner(void);
+WindowPtr nxagentGetClipboardWindow(Atom property, WindowPtr pWin);
+void nxagentNotifyConvertFailure(ClientPtr client, Window requestor,
+ Atom selection, Atom target, Time time);
+int nxagentSendNotify(xEvent *event);
+
+/*
+ * This is from NXproperty.c.
+ */
+
+int GetWindowProperty(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);
+
+Bool nxagentValidServerTargets(Atom target)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentValidServerTargets: Got called.\n");
+ #endif
+
+ if (target == XA_STRING) return True;
+ if (target == serverTEXT) return True;
+ /* by dimbor */
+ if (target == serverUTF8_STRING) return True;
+
+ return False;
+}
+
+void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow)
+{
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearClipboard: Called with client [%p] window [%p].\n",
+ (void *) pClient, (void *) pWindow);
+ #endif
+
+ /*
+ * Only for PRIMARY and CLIPBOARD selections.
+ */
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ if ((pClient != NULL && lastSelectionOwner[i].client == pClient) ||
+ (pWindow != NULL && lastSelectionOwner[i].windowPtr == pWindow))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentClearClipboard: Resetting state with client [%p] window [%p].\n",
+ (void *) pClient, (void *) pWindow);
+ #endif
+
+ lastSelectionOwner[i].client = NULL;
+ lastSelectionOwner[i].window = None;
+ lastSelectionOwner[i].windowPtr = NULL;
+ lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis();
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ lastServerRequestor = None;
+ }
+ }
+
+ if (pWindow == lastClientWindowPtr)
+ {
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+ }
+
+}
+
+void nxagentClearSelection(XEvent *X)
+{
+ int i = 0;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearSelection: Got called.\n");
+ #endif
+
+ if (agentClipboardStatus != 1 ||
+ nxagentOption(Clipboard) == ClipboardServer)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearSelection: SelectionClear event.\n");
+ #endif
+
+ while ((i < nxagentMaxSelections) &&
+ (lastSelectionOwner[i].selection != X->xselectionclear.selection))
+ {
+ i++;
+ }
+
+ if (i < nxagentMaxSelections)
+ {
+ if (lastSelectionOwner[i].client != NULL)
+ {
+ xEvent x;
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionClear;
+ x.u.selectionClear.time = GetTimeInMillis();
+ x.u.selectionClear.window = lastSelectionOwner[i].window;
+ x.u.selectionClear.atom = CurrentSelections[i].selection;
+
+ (void) TryClientEvents(lastSelectionOwner[i].client, &x, 1,
+ NoEventMask, NoEventMask,
+ NullGrab);
+ }
+
+ CurrentSelections[i].window = screenInfo.screens[0]->root->drawable.id;
+ CurrentSelections[i].client = NullClient;
+
+ lastSelectionOwner[i].client = NULL;
+ lastSelectionOwner[i].window = None;
+ lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis();
+ }
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+}
+
+void nxagentRequestSelection(XEvent *X)
+{
+ #ifdef DEBUG
+ int result;
+ #endif
+ int i = 0;
+ XSelectionEvent eventSelection;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRequestSelection: Got called.\n");
+ #endif
+
+ if (agentClipboardStatus != 1)
+ {
+ return;
+ }
+
+ if (!nxagentValidServerTargets(X->xselectionrequest.target) ||
+ (lastServerRequestor != None) ||
+ ((X->xselectionrequest.selection != lastSelectionOwner[nxagentPrimarySelection].selection) &&
+ (X->xselectionrequest.selection != lastSelectionOwner[nxagentClipboardSelection].selection)))
+ {
+/*
+FIXME: Do we need this?
+
+ char *strTarget;
+
+ strTarget = XGetAtomName(nxagentDisplay, X->xselectionrequest.target);
+
+ fprintf(stderr, "SelectionRequest event aborting sele=[%s] target=[%s]\n",
+ validateString(NameForAtom(X->xselectionrequest.selection)),
+ validateString(NameForAtom(X->xselectionrequest.target)));
+
+ fprintf(stderr, "SelectionRequest event aborting sele=[%s] ext target=[%s] Atom size is [%d]\n",
+ validateString(NameForAtom(X->xselectionrequest.selection)), strTarget, sizeof(Atom));
+
+ if (strTarget != NULL)
+ {
+ XFree(strTarget);
+ }
+*/
+ memset(&eventSelection, 0, sizeof(XSelectionEvent));
+ eventSelection.property = None;
+
+ if (X->xselectionrequest.target == serverTARGETS)
+ {
+ Atom xa_STRING = XA_STRING;
+ XChangeProperty (nxagentDisplay,
+ X->xselectionrequest.requestor,
+ X->xselectionrequest.property,
+ XInternAtom(nxagentDisplay, "ATOM", 0),
+ sizeof(Atom)*8,
+ PropModeReplace,
+ (unsigned char*)&xa_STRING,
+ 1);
+ eventSelection.property = X->xselectionrequest.property;
+ }
+
+ if (X->xselectionrequest.target == nxagentTimestampAtom)
+ {
+ while ((i < NumCurrentSelections) &&
+ lastSelectionOwner[i].selection != X->xselectionrequest.selection) i++;
+
+ if (i < NumCurrentSelections)
+ {
+ XChangeProperty(nxagentDisplay,
+ X->xselectionrequest.requestor,
+ X->xselectionrequest.property,
+ X->xselectionrequest.target,
+ 32,
+ PropModeReplace,
+ (unsigned char *) &lastSelectionOwner[i].lastTimeChanged,
+ 1);
+ eventSelection.property = X->xselectionrequest.property;
+ }
+ }
+
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = nxagentDisplay;
+ eventSelection.requestor = X->xselectionrequest.requestor;
+ eventSelection.selection = X->xselectionrequest.selection;
+ eventSelection.target = X->xselectionrequest.target;
+ eventSelection.time = X->xselectionrequest.time;
+
+ #ifdef DEBUG
+ result =
+ #endif
+ XSendEvent(nxagentDisplay,
+ eventSelection.requestor,
+ False,
+ 0L,
+ (XEvent *) &eventSelection);
+
+ #ifdef DEBUG
+ if (result == BadValue || result == BadWindow)
+ {
+ fprintf(stderr, "nxagentRequestSelection: WARNING! XSendEvent failed.\n");
+ }
+ else
+ {
+ fprintf(stderr, "nxagentRequestSelection: XSendEvent sent to window [0x%lx].\n",
+ eventSelection.requestor);
+ }
+ #endif
+
+ return;
+ }
+
+ /*
+ * This is necessary in nxagentGetClipboardWindow.
+ */
+
+ nxagentLastRequestedSelection = X->xselectionrequest.selection;
+
+ while ((i < nxagentMaxSelections) &&
+ (lastSelectionOwner[i].selection != X->xselectionrequest.selection))
+ {
+ i++;
+ }
+
+ if (i < nxagentMaxSelections)
+ {
+ if ((lastClientWindowPtr != NULL) && (lastSelectionOwner[i].client != NULL))
+ {
+ XConvertSelection(nxagentDisplay, CurrentSelections[i].selection,
+ X->xselectionrequest.target, serverCutProperty,
+ serverWindow, lastClientTime);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRequestSelection: Sent XConvertSelection.\n");
+ #endif
+ }
+ else
+ {
+ if (lastSelectionOwner[i].client != NULL &&
+ nxagentOption(Clipboard) != ClipboardClient)
+ {
+ xEvent x;
+
+ lastServerProperty = X->xselectionrequest.property;
+ lastServerRequestor = X->xselectionrequest.requestor;
+ lastServerTarget = X->xselectionrequest.target;
+
+ /* by dimbor */
+ if (lastServerTarget != XA_STRING)
+ lastServerTarget = serverUTF8_STRING;
+
+ lastServerTime = X->xselectionrequest.time;
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionRequest;
+ x.u.selectionRequest.time = GetTimeInMillis();
+ x.u.selectionRequest.owner = lastSelectionOwner[i].window;
+
+ /*
+ * Fictitious window.
+ */
+
+ x.u.selectionRequest.requestor = screenInfo.screens[0]->root->drawable.id;
+
+ /*
+ * Don't send the same window, some programs are
+ * clever and verify cut and paste operations
+ * inside the same window and don't Notify at all.
+ *
+ * x.u.selectionRequest.requestor = lastSelectionOwnerWindow;
+ */
+
+ x.u.selectionRequest.selection = CurrentSelections[i].selection;
+
+ /* by dimbor (idea from zahvatov) */
+ if (X->xselectionrequest.target != XA_STRING)
+ x.u.selectionRequest.target = clientUTF8_STRING;
+ else
+ x.u.selectionRequest.target = XA_STRING;
+
+ x.u.selectionRequest.property = clientCutProperty;
+
+ (void) TryClientEvents(lastSelectionOwner[i].client, &x, 1,
+ NoEventMask, NoEventMask /* CantBeFiltered */,
+ NullGrab);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRequestSelection: Executed TryClientEvents with clientCutProperty.\n");
+ #endif
+ }
+ else
+ {
+ /*
+ * Probably we must to send a Notify
+ * to requestor with property None.
+ */
+
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = nxagentDisplay;
+ eventSelection.requestor = X->xselectionrequest.requestor;
+ eventSelection.selection = X->xselectionrequest.selection;
+ eventSelection.target = X->xselectionrequest.target;
+ eventSelection.property = None;
+ eventSelection.time = X->xselectionrequest.time;
+
+ #ifdef DEBUG
+ result =
+ #endif
+ XSendEvent(nxagentDisplay,
+ eventSelection.requestor,
+ False,
+ 0L,
+ (XEvent *) &eventSelection);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRequestSelection: Executed XSendEvent with property None.\n");
+ #endif
+ }
+ }
+ }
+}
+
+void nxagentSendSelectionNotify(Atom property)
+{
+ xEvent x;
+
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentSendSelectionNotify: Sending event to client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionNotify;
+
+ x.u.selectionNotify.time = lastClientTime;
+ x.u.selectionNotify.requestor = lastClientRequestor;
+ x.u.selectionNotify.selection = lastClientSelection;
+ x.u.selectionNotify.target = lastClientTarget;
+
+ x.u.selectionNotify.property = property;
+
+ TryClientEvents(lastClientClientPtr, &x, 1, NoEventMask,
+ NoEventMask , NullGrab);
+
+ return;
+}
+
+void nxagentTransferSelection(int resource)
+{
+ int result;
+
+ if (lastClientClientPtr -> index != resource)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: WARNING! Inconsistent resource [%d] with current client [%d].\n",
+ resource, lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ return;
+ }
+
+ switch (lastClientStage)
+ {
+ case SelectionStageQuerySize:
+ {
+ /*
+ * Don't get data yet, just get size. We skip
+ * this stage in current implementation and
+ * go straight to the data.
+ */
+
+ nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay);
+
+ if (nxagentLastClipboardClient == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentTransferSelection: WARNING! Asynchronous GetProperty queue full.\n");
+ #endif
+
+ result = -1;
+ }
+ else
+ {
+ result = NXCollectProperty(nxagentDisplay,
+ nxagentLastClipboardClient,
+ serverWindow,
+ serverCutProperty,
+ 0,
+ 0,
+ False,
+ AnyPropertyType);
+ }
+
+ if (result == -1)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: Aborting selection notify procedure for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: Setting stage to [%d] for client [%d].\n",
+ SelectionStageWaitSize, lastClientClientPtr -> index);
+ #endif
+
+ lastClientStage = SelectionStageWaitSize;
+
+ break;
+ }
+ case SelectionStageQueryData:
+ {
+ /*
+ * Request the selection data now.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTransferSelection: Getting property content from remote server.\n");
+ #endif
+
+ nxagentLastClipboardClient = NXGetCollectPropertyResource(nxagentDisplay);
+
+ if (nxagentLastClipboardClient == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentTransferSelection: WARNING! Asynchronous GetProperty queue full.\n");
+ #endif
+
+ result = -1;
+ }
+ else
+ {
+ result = NXCollectProperty(nxagentDisplay,
+ nxagentLastClipboardClient,
+ serverWindow,
+ serverCutProperty,
+ 0,
+ lastClientPropertySize,
+ False,
+ AnyPropertyType);
+ }
+
+ if (result == -1)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: Aborting selection notify procedure for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: Setting stage to [%d] for client [%d].\n",
+ SelectionStageWaitData, lastClientClientPtr -> index);
+ #endif
+
+ lastClientStage = SelectionStageWaitData;
+
+ break;
+ }
+ default:
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentTransferSelection: WARNING! Inconsistent state [%d] for client [%d].\n",
+ lastClientStage, lastClientClientPtr -> index);
+ #endif
+
+ break;
+ }
+ }
+}
+
+void nxagentCollectPropertyEvent(int resource)
+{
+ Atom atomReturnType;
+ int resultFormat;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+ int result;
+
+ /*
+ * We have received the notification so
+ * we can safely retrieve data from the
+ * client structure.
+ */
+
+ result = NXGetCollectedProperty(nxagentDisplay,
+ resource,
+ &atomReturnType,
+ &resultFormat,
+ &ulReturnItems,
+ &ulReturnBytesLeft,
+ &pszReturnData);
+
+ nxagentLastClipboardClient = -1;
+
+ if (result == 0)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: Failed to get reply data for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ if (pszReturnData != NULL)
+ {
+ XFree(pszReturnData);
+ }
+
+ return;
+ }
+
+ if (resultFormat != 8 && resultFormat != 16 && resultFormat != 32)
+ {
+
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: WARNING! Invalid property "
+ "value.\n");
+ #endif
+
+ if (lastClientClientPtr != NULL)
+ {
+ nxagentSendSelectionNotify(None);
+ }
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ if (pszReturnData != NULL)
+ {
+ XFree(pszReturnData);
+ }
+
+ return;
+ }
+
+ switch (lastClientStage)
+ {
+ case SelectionStageWaitSize:
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: Got size notify event for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ if (ulReturnBytesLeft == 0)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: Aborting selection notify procedure for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ if (pszReturnData != NULL)
+ {
+ free(pszReturnData);
+ }
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCollectPropertyEvent: Got property size from remote server.\n");
+ #endif
+
+ /*
+ * Request the selection data now.
+ */
+
+ lastClientPropertySize = ulReturnBytesLeft;
+ lastClientStage = SelectionStageQueryData;
+
+ nxagentTransferSelection(resource);
+
+ break;
+ }
+ case SelectionStageWaitData:
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: Got data notify event for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ if (ulReturnBytesLeft != 0)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: Aborting selection notify procedure for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ if (pszReturnData != NULL)
+ {
+ free(pszReturnData);
+ }
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCollectPropertyEvent: Got property content from remote server.\n");
+ #endif
+
+ ChangeWindowProperty(lastClientWindowPtr,
+ lastClientProperty,
+ lastClientTarget,
+ resultFormat, PropModeReplace,
+ ulReturnItems, pszReturnData, 1);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCollectPropertyEvent: Selection property [%s] changed to [%s]\n",
+ validateString(NameForAtom(lastClientProperty)), pszReturnData);
+ #endif
+
+ nxagentSendSelectionNotify(lastClientProperty);
+
+ /*
+ * Enable further requests from clients.
+ */
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ break;
+ }
+ default:
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentCollectPropertyEvent: WARNING! Inconsistent state [%d] for client [%d].\n",
+ lastClientStage, lastClientClientPtr -> index);
+ #endif
+
+ break;
+ }
+ }
+
+ XFree(pszReturnData);
+ pszReturnData = NULL;
+}
+
+void nxagentNotifySelection(XEvent *X)
+{
+ int result;
+
+ XSelectionEvent eventSelection;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentNotifySelection: Got called.\n");
+ #endif
+
+ if (agentClipboardStatus != 1)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentNotifySelection: SelectionNotify event.\n");
+ #endif
+
+ if (lastClientWindowPtr != NULL)
+ {
+ if ((lastClientStage == SelectionStageNone) && (X->xselection.property == serverCutProperty))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentNotifySelection: Starting selection transferral for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ /*
+ * The state machine is able to work in two phases. In the first
+ * phase we get the size of property data, in the second we get
+ * the actual data. We save a round-trip by requesting a prede-
+ * termined amount of data in a single GetProperty and by discar-
+ * ding the remaining part. This is not the optimal solution (we
+ * could get the remaining part if it doesn't fit in a single
+ * reply) but, at least with text, it should work in most situa-
+ * tions.
+ */
+
+ lastClientStage = SelectionStageQueryData;
+ lastClientPropertySize = 262144;
+
+ nxagentTransferSelection(lastClientClientPtr -> index);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentNotifySelection: WARNING! Resetting selection transferral for client [%d].\n",
+ lastClientClientPtr -> index);
+ #endif
+
+ nxagentSendSelectionNotify(None);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+ }
+
+ return;
+ }
+ else
+ {
+ int i = 0;
+
+ while ((i < nxagentMaxSelections) && (lastSelectionOwner[i].selection != X->xselection.selection))
+ {
+ i++;
+ }
+
+ if (i < nxagentMaxSelections)
+ {
+ if ((lastSelectionOwner[i].client != NULL) &&
+ (lastSelectionOwner[i].windowPtr != NULL) &&
+ (X->xselection.property == clientCutProperty))
+ {
+ Atom atomReturnType;
+ int resultFormat;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+
+ result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0, 0, False,
+ AnyPropertyType, &atomReturnType, &resultFormat,
+ &ulReturnItems, &ulReturnBytesLeft, &pszReturnData);
+
+ if (result == BadAlloc || result == BadAtom ||
+ result == BadMatch || result == BadValue ||
+ result == BadWindow)
+ {
+ fprintf (stderr, "Client GetProperty failed error =");
+ lastServerProperty = None;
+ switch (result)
+ {
+ case BadAtom:
+ fprintf (stderr, "BadAtom\n");
+ break;
+ case BadValue:
+ fprintf (stderr, "BadValue\n");
+ break;
+ case BadWindow:
+ fprintf (stderr, "BadWindow\n");
+ break;
+ }
+ }
+ else
+ {
+ result = GetWindowProperty(lastSelectionOwner[i].windowPtr, clientCutProperty, 0,
+ ulReturnBytesLeft, False, AnyPropertyType, &atomReturnType,
+ &resultFormat, &ulReturnItems, &ulReturnBytesLeft,
+ &pszReturnData);
+
+ if (result == BadAlloc || result == BadAtom ||
+ result == BadMatch || result == BadValue ||
+ result == BadWindow)
+ {
+ fprintf (stderr, "SelectionNotify - XChangeProperty failed\n");
+
+ lastServerProperty = None;
+ }
+ else
+ {
+ result = XChangeProperty(nxagentDisplay,
+ lastServerRequestor,
+ lastServerProperty,
+ lastServerTarget,
+ 8,
+ PropModeReplace,
+ pszReturnData,
+ ulReturnItems);
+ }
+
+ /*
+ * if (pszReturnData)
+ * {
+ * free(pszReturnData);
+ * pszReturnData=NULL;
+ * }
+ */
+
+ }
+
+ memset(&eventSelection, 0, sizeof(XSelectionEvent));
+ eventSelection.type = SelectionNotify;
+ eventSelection.send_event = True;
+ eventSelection.display = nxagentDisplay;
+ eventSelection.requestor = lastServerRequestor;
+
+ eventSelection.selection = X->xselection.selection;
+
+ /*
+ * eventSelection.target = X->xselection.target;
+ */
+
+ eventSelection.target = lastServerTarget;
+ eventSelection.property = lastServerProperty;
+ eventSelection.time = lastServerTime;
+
+ /*
+ * eventSelection.time = CurrentTime;
+ * eventSelection.time = lastServerTime;
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentNotifySelection: Sending event to requestor.\n");
+ #endif
+
+ result = XSendEvent(nxagentDisplay,
+ eventSelection.requestor,
+ False,
+ 0L,
+ (XEvent *) &eventSelection);
+
+ if (result == BadValue || result == BadWindow)
+ {
+ fprintf (stderr, "SelectionRequest - XSendEvent failed\n");
+ }
+
+ lastServerRequestor = None; /* allow further request */
+ }
+ }
+ }
+}
+
+/*
+ * Acquire selection so we don't get selection
+ * requests from real X clients.
+ */
+
+void nxagentResetSelectionOwner()
+{
+ int i;
+
+ if (lastServerRequestor != None)
+ {
+ #ifdef TEST
+ fprintf (stderr, "nxagentResetSelectionOwner: WARNING! Requestor window [0x%lx] already found.\n",
+ lastServerRequestor);
+ #endif
+
+ return;
+ }
+
+ /*
+ * Only for PRIMARY and CLIPBOARD selections.
+ */
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime);
+
+ fprintf (stderr, "nxagentResetSelectionOwner: Reset clipboard state.\n");
+
+ lastSelectionOwner[i].client = NULL;
+ lastSelectionOwner[i].window = None;
+ lastSelectionOwner[i].windowPtr = NULL;
+ lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis();
+ }
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ lastServerRequestor = None;
+
+ return;
+}
+
+void nxagentSetSelectionOwner(Selection *pSelection)
+{
+ int i;
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetSelectionOwner: Got called.\n");
+ #endif
+
+ if (agentClipboardStatus != 1)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetSelectionOwner: Setting selection owner to window [0x%lx].\n",
+ serverWindow);
+ #endif
+
+ #ifdef TEST
+ if (lastServerRequestor != None)
+ {
+ fprintf (stderr, "nxagentSetSelectionOwner: WARNING! Requestor window [0x%lx] already found.\n",
+ lastServerRequestor);
+ }
+ #endif
+
+ /*
+ * Only for PRIMARY and CLIPBOARD selections.
+ */
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ if (pSelection->selection == CurrentSelections[i].selection)
+ {
+ XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, serverWindow, CurrentTime);
+
+ lastSelectionOwner[i].client = pSelection->client;
+ lastSelectionOwner[i].window = pSelection->window;
+ lastSelectionOwner[i].windowPtr = pSelection->pWin;
+ lastSelectionOwner[i].lastTimeChanged = GetTimeInMillis();
+ }
+ }
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ lastServerRequestor = None;
+
+/*
+FIXME
+
+ if (XGetSelectionOwner(nxagentDisplay,pSelection->selection)==serverWindow)
+ {
+ fprintf (stderr, "NXdispatch: SetSelectionOwner OK\n");
+
+ lastSelectionOwnerSelection = pSelection;
+ lastSelectionOwnerClient = pSelection->client;
+ lastSelectionOwnerWindow = pSelection->window;
+ lastSelectionOwnerWindowPtr = pSelection->pWin;
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+
+ lastServerRequestor = None;
+ }
+ else fprintf (stderr, "nxagentSetSelectionOwner: SetSelectionOwner failed\n");
+*/
+}
+
+void nxagentNotifyConvertFailure(ClientPtr client, Window requestor,
+ Atom selection, Atom target, Time time)
+{
+ xEvent x;
+
+/*
+FIXME: Why this pointer can be not a valid
+ client pointer?
+*/
+ if (clients[client -> index] != client)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentNotifyConvertFailure: WARNING! Invalid client pointer.");
+ #endif
+
+ return;
+ }
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionNotify;
+ x.u.selectionNotify.time = time;
+ x.u.selectionNotify.requestor = requestor;
+ x.u.selectionNotify.selection = selection;
+ x.u.selectionNotify.target = target;
+ x.u.selectionNotify.property = None;
+
+ (void) TryClientEvents(client, &x, 1, NoEventMask,
+ NoEventMask , NullGrab);
+}
+
+int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection,
+ Window requestor, Atom property, Atom target, Time time)
+{
+ const char *strTarget;
+ int i;
+
+ if (agentClipboardStatus != 1 ||
+ nxagentOption(Clipboard) == ClipboardServer)
+ {
+ return 0;
+ }
+
+ /*
+ * There is a client owner on the agent side, let normal stuff happen.
+ */
+
+ /*
+ * Only for PRIMARY and CLIPBOARD selections.
+ */
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ if ((selection == CurrentSelections[i].selection) &&
+ (lastSelectionOwner[i].client != NULL))
+ {
+ return 0;
+ }
+ }
+
+ if (lastClientWindowPtr != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConvertSelection: lastClientWindowPtr != NULL.\n");
+ #endif
+
+ if ((GetTimeInMillis() - lastClientReqTime) > 5000)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentConvertSelection: timeout expired on last request, "
+ "notifying failure to client\n");
+ #endif
+
+ nxagentNotifyConvertFailure(lastClientClientPtr, lastClientRequestor,
+ lastClientSelection, lastClientTarget, lastClientTime);
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentConvertSelection: got request "
+ "before timeout expired on last request, notifying failure to client\n");
+ #endif
+
+ nxagentNotifyConvertFailure(client, requestor, selection, target, time);
+
+ return 1;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentConvertSelection: client [%d] ask for sel [%s] "
+ "on window [%lx] prop [%s] target [%s].\n",
+ client -> index, validateString(NameForAtom(selection)), requestor,
+ validateString(NameForAtom(property)), validateString(NameForAtom(target)));
+ #endif
+
+ strTarget = NameForAtom(target);
+
+ if (strTarget == NULL)
+ {
+ return 1;
+ }
+
+ if (target == clientTARGETS)
+ {
+ Atom xa_STRING[4];
+ xEvent x;
+
+ /* --- Order changed by dimbor (prevent sending COMPOUND_TEXT to client --- */
+ xa_STRING[0] = XA_STRING;
+ xa_STRING[1] = clientUTF8_STRING;
+ xa_STRING[2] = clientTEXT;
+ xa_STRING[3] = clientCOMPOUND_TEXT;
+
+ ChangeWindowProperty(pWin,
+ property,
+ MakeAtom("ATOM", 4, 1),
+ sizeof(Atom)*8,
+ PropModeReplace,
+ 4,
+ &xa_STRING, 1);
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionNotify;
+ x.u.selectionNotify.time = time;
+ x.u.selectionNotify.requestor = requestor;
+ x.u.selectionNotify.selection = selection;
+ x.u.selectionNotify.target = target;
+ x.u.selectionNotify.property = property;
+
+ (void) TryClientEvents(client, &x, 1, NoEventMask,
+ NoEventMask , NullGrab);
+
+ return 1;
+ }
+
+ if (target == MakeAtom("TIMESTAMP", 9, 1))
+ {
+ xEvent x;
+ int i = 0;
+
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != selection) i++;
+
+ if (i < NumCurrentSelections)
+ {
+ ChangeWindowProperty(pWin,
+ property,
+ target,
+ 32,
+ PropModeReplace,
+ 1,
+ (unsigned char *) &lastSelectionOwner[i].lastTimeChanged,
+ 1);
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionNotify;
+ x.u.selectionNotify.time = time;
+ x.u.selectionNotify.requestor = requestor;
+ x.u.selectionNotify.selection = selection;
+ x.u.selectionNotify.target = target;
+ x.u.selectionNotify.property = property;
+
+ (void) TryClientEvents(client, &x, 1, NoEventMask,
+ NoEventMask , NullGrab);
+
+ return 1;
+
+ }
+ }
+
+ if (lastClientClientPtr == client && (GetTimeInMillis() - lastClientReqTime < 5000))
+ {
+ /*
+ * The same client made consecutive requests
+ * of clipboard contents with less than 5
+ * seconds time interval between them.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentConvertSelection: Consecutives request from client [%p] selection [%ld] "
+ "elapsed time [%lu] clientAccum [%d]\n", (void *) client, selection,
+ GetTimeInMillis() - lastClientReqTime, clientAccum);
+ #endif
+
+ clientAccum++;
+ }
+ else
+ {
+ if (lastClientClientPtr != client)
+ {
+ clientAccum = 0;
+ }
+ }
+
+ if ((target == clientTEXT) ||
+ (target == XA_STRING) ||
+ (target == clientCOMPOUND_TEXT) ||
+ (target == clientUTF8_STRING))
+ {
+ lastClientWindowPtr = pWin;
+ lastClientStage = SelectionStageNone;
+ lastClientRequestor = requestor;
+ lastClientClientPtr = client;
+ lastClientTime = time;
+ lastClientProperty = property;
+ lastClientSelection = selection;
+ lastClientTarget = target;
+
+ lastClientReqTime = (GetTimeInMillis() - lastClientReqTime) > 5000 ?
+ GetTimeInMillis() : lastClientReqTime;
+
+ if (selection == MakeAtom("CLIPBOARD", 9, 0))
+ {
+ selection = lastSelectionOwner[nxagentClipboardSelection].selection;
+ }
+
+ if (target == clientUTF8_STRING)
+ {
+ XConvertSelection(nxagentDisplay, selection, serverUTF8_STRING, serverCutProperty,
+ serverWindow, CurrentTime);
+ }
+ else
+ {
+ XConvertSelection(nxagentDisplay, selection, XA_STRING, serverCutProperty,
+ serverWindow, CurrentTime);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentConvertSelection: Sent XConvertSelection with target=[%s], property [%s]\n",
+ validateString(NameForAtom(target)), validateString(NameForAtom(property)));
+ #endif
+
+ return 1;
+ }
+ else
+ {
+ xEvent x;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentConvertSelection: Xserver generates a SelectionNotify event "
+ "to the requestor with property None.\n");
+ #endif
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = SelectionNotify;
+ x.u.selectionNotify.time = time;
+ x.u.selectionNotify.requestor = requestor;
+ x.u.selectionNotify.selection = selection;
+ x.u.selectionNotify.target = target;
+ x.u.selectionNotify.property = None;
+ (void) TryClientEvents(client, &x, 1, NoEventMask, NoEventMask , NullGrab);
+ return 1;
+ }
+ return 0;
+}
+
+int nxagentSendNotify(xEvent *event)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSendNotify: Got called.\n");
+ #endif
+
+ if (agentClipboardStatus != 1)
+ {
+ return 0;
+ }
+
+ if (event->u.selectionNotify.property == clientCutProperty)
+ {
+ XSelectionEvent x;
+ int result;
+
+ /*
+ * Setup selection notify event to real server.
+ */
+
+ memset(&x, 0, sizeof(XSelectionEvent));
+ x.type = SelectionNotify;
+ x.send_event = True;
+ x.display = nxagentDisplay;
+ x.requestor = serverWindow;
+
+ /*
+ * On real server, the right CLIPBOARD atom is
+ * XInternAtom(nxagentDisplay, "CLIPBOARD", 1).
+ */
+
+ if (event->u.selectionNotify.selection == MakeAtom("CLIPBOARD", 9, 0))
+ {
+ x.selection = lastSelectionOwner[nxagentClipboardSelection].selection;
+ }
+ else
+ {
+ x.selection = event->u.selectionNotify.selection;
+ }
+
+ x.target = event->u.selectionNotify.target;
+ x.property = event->u.selectionNotify.property;
+ x.time = CurrentTime;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSendNotify: Propagating clientCutProperty.\n");
+ #endif
+
+ result = XSendEvent (nxagentDisplay, x.requestor, False,
+ 0L, (XEvent *) &x);
+
+ if (result == BadValue || result == BadWindow)
+ {
+ fprintf (stderr, "nxagentSendNotify: XSendEvent failed.\n");
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+WindowPtr nxagentGetClipboardWindow(Atom property, WindowPtr pWin)
+{
+ int i = 0;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetClipboardWindow: Got called.\n");
+ #endif
+
+ while ((i < nxagentMaxSelections) &&
+ (lastSelectionOwner[i].selection != nxagentLastRequestedSelection))
+ {
+ i++;
+ }
+
+ if ((i < nxagentMaxSelections) && (property == clientCutProperty) &&
+ (lastSelectionOwner[i].windowPtr != NULL))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetClipboardWindow: Returning last clipboard owner window.\n");
+ #endif
+
+ return lastSelectionOwner[i].windowPtr;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetClipboardWindow: Returning original target window.\n");
+ #endif
+
+ return pWin;
+ }
+
+}
+
+int nxagentInitClipboard(WindowPtr pWin)
+{
+ int i;
+ Window iWindow = nxagentWindow(pWin);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitClipboard: Got called.\n");
+ #endif
+
+ if (lastSelectionOwner != NULL)
+ {
+ free(lastSelectionOwner);
+ lastSelectionOwner = NULL;
+ }
+
+ lastSelectionOwner = (SelectionOwner *) malloc(2 * sizeof(SelectionOwner));
+
+ if (lastSelectionOwner == NULL)
+ {
+ FatalError("nxagentInitClipboard: Failed to allocate memory for the clipboard selections.\n");
+ }
+
+ nxagentClipboardAtom = nxagentAtoms[10]; /* CLIPBOARD */
+ nxagentTimestampAtom = nxagentAtoms[11]; /* TIMESTAMP */
+
+ lastSelectionOwner[nxagentPrimarySelection].selection = XA_PRIMARY;
+ lastSelectionOwner[nxagentPrimarySelection].client = NullClient;
+ lastSelectionOwner[nxagentPrimarySelection].window = screenInfo.screens[0]->root->drawable.id;
+ lastSelectionOwner[nxagentPrimarySelection].windowPtr = NULL;
+ lastSelectionOwner[nxagentPrimarySelection].lastTimeChanged = GetTimeInMillis();
+
+ lastSelectionOwner[nxagentClipboardSelection].selection = nxagentClipboardAtom;
+ lastSelectionOwner[nxagentClipboardSelection].client = NullClient;
+ lastSelectionOwner[nxagentClipboardSelection].window = screenInfo.screens[0]->root->drawable.id;
+ lastSelectionOwner[nxagentClipboardSelection].windowPtr = NULL;
+ lastSelectionOwner[nxagentClipboardSelection].lastTimeChanged = GetTimeInMillis();
+
+ #ifdef NXAGENT_TIMESTAMP
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "nxagentInitClipboard: Initializing start [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+ #endif
+
+ agentClipboardStatus = 0;
+ serverWindow = iWindow;
+
+ /*
+ * Local property to hold pasted data.
+ */
+
+ serverCutProperty = nxagentAtoms[5]; /* NX_CUT_BUFFER_SERVER */
+ serverTARGETS = nxagentAtoms[6]; /* TARGETS */
+ serverTEXT = nxagentAtoms[7]; /* TEXT */
+ serverUTF8_STRING = nxagentAtoms[12]; /* UTF8_STRING */
+
+ if (serverCutProperty == None)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentInitClipboard: PANIC! Could not create NX_CUT_BUFFER_SERVER atom\n");
+ #endif
+
+ return -1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitClipboard: Setting owner of selection [%s][%d] on window 0x%lx\n",
+ "NX_CUT_BUFFER_SERVER", (int) serverCutProperty, iWindow);
+ #endif
+
+ XSetSelectionOwner(nxagentDisplay, serverCutProperty, iWindow, CurrentTime);
+
+ if (XQueryExtension(nxagentDisplay,
+ "XFIXES",
+ &nxagentXFixesInfo.Opcode,
+ &nxagentXFixesInfo.EventBase,
+ &nxagentXFixesInfo.ErrorBase) == 0)
+ {
+ ErrorF("Unable to initialize XFixes extension.\n");
+ }
+
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitClipboard: Registering for XFixesSelectionNotify events.\n");
+ #endif
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ XFixesSelectSelectionInput(nxagentDisplay, iWindow,
+ lastSelectionOwner[i].selection,
+ XFixesSetSelectionOwnerNotifyMask |
+ XFixesSelectionWindowDestroyNotifyMask |
+ XFixesSelectionClientCloseNotifyMask);
+ }
+
+ nxagentXFixesInfo.Initialized = 1;
+ }
+
+ /*
+ The first paste from CLIPBOARD did not work directly after
+ session start. Removing this code makes it work. It is unsure why
+ it was introduced in the first place so it is possible that we
+ see other effects by leaving out this code.
+
+ Fixes X2Go bug #952, see https://bugs.x2go.org/952 for details .
+
+ if (nxagentSessionId[0])
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitClipboard: setting the ownership of %s to %lx"
+ " and registering for PropertyChangeMask events\n",
+ validateString(XGetAtomName(nxagentDisplay, nxagentAtoms[10])), iWindow);
+ #endif
+
+ XSetSelectionOwner(nxagentDisplay, nxagentAtoms[10], iWindow, CurrentTime);
+ pWin -> eventMask |= PropertyChangeMask;
+ nxagentChangeWindowAttributes(pWin, CWEventMask);
+ }
+ */
+
+ if (nxagentReconnectTrap)
+ {
+ /*
+ * Only for PRIMARY and CLIPBOARD selections.
+ */
+
+ for (i = 0; i < nxagentMaxSelections; i++)
+ {
+ if (lastSelectionOwner[i].client && lastSelectionOwner[i].window)
+ {
+ XSetSelectionOwner(nxagentDisplay, lastSelectionOwner[i].selection, iWindow, CurrentTime);
+ }
+ }
+ }
+ else
+ {
+ lastSelectionOwner[nxagentPrimarySelection].client = NULL;
+ lastSelectionOwner[nxagentClipboardSelection].client = NULL;
+
+ lastServerRequestor = None;
+
+ lastClientWindowPtr = NULL;
+ lastClientStage = SelectionStageNone;
+ lastClientReqTime = GetTimeInMillis();
+
+ clientCutProperty = MakeAtom(szAgentNX_CUT_BUFFER_CLIENT,
+ strlen(szAgentNX_CUT_BUFFER_CLIENT), 1);
+ clientTARGETS = MakeAtom(szAgentTARGETS, strlen(szAgentTARGETS), True);
+ clientTEXT = MakeAtom(szAgentTEXT, strlen(szAgentTEXT), True);
+ clientCOMPOUND_TEXT = MakeAtom(szAgentCOMPOUND_TEXT, strlen(szAgentCOMPOUND_TEXT), True);
+ clientUTF8_STRING = MakeAtom(szAgentUTF8_STRING, strlen(szAgentUTF8_STRING), True);
+
+ if (clientCutProperty == None)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentInitClipboard: PANIC! "
+ "Could not create NX_CUT_BUFFER_CLIENT atom.\n");
+ #endif
+
+ return -1;
+ }
+ }
+
+ agentClipboardStatus = 1;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitClipboard: Clipboard initialization completed.\n");
+ #endif
+
+ #ifdef NXAGENT_TIMESTAMP
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "nxagentInitClipboard: initializing ends [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+ #endif
+
+ return 1;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h
new file mode 100644
index 000000000..62fc32fd9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Clipboard.h
@@ -0,0 +1,69 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Clipboard_H__
+#define __Clipboard_H__
+
+/*
+ * Queried at clipboard initialization.
+ */
+
+typedef struct _XFixesAgentInfo
+{
+ int Opcode;
+ int EventBase;
+ int ErrorBase;
+ int Initialized;
+
+} XFixesAgentInfoRec;
+
+extern XFixesAgentInfoRec nxagentXFixesInfo;
+
+/*
+ * Create the NX_CUT_BUFFER_CLIENT atom and
+ * initialize the required property to exchange
+ * data with the X server.
+ */
+
+extern int nxagentInitClipboard(WindowPtr pWindow);
+
+/*
+ * Called whenever a client or a window is
+ * destroyed to let the clipboard code to
+ * release any pointer to the referenced
+ * structures.
+ */
+
+extern void nxagentClearClipboard(ClientPtr pClient, WindowPtr pWindow);
+
+extern void nxagentSetSelectionOwner(Selection *pSelection);
+extern int nxagentConvertSelection(ClientPtr client, WindowPtr pWin, Atom selection,
+ Window requestor, Atom property, Atom target, Time time);
+
+void nxagentClearSelection();
+void nxagentRequestSelection();
+void nxagentNotifySelection();
+
+#endif /* __Clipboard_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Colormap.c b/nx-X11/programs/Xserver/hw/nxagent/Colormap.c
new file mode 100644
index 000000000..c21bcbbe7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.c
@@ -0,0 +1,600 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "scrnintstr.h"
+#include "../../include/window.h"
+#include "windowstr.h"
+#include "colormapst.h"
+#include "resource.h"
+
+#include "Agent.h"
+
+
+#include "Display.h"
+#include "Screen.h"
+#include "Colormap.h"
+#include "Visual.h"
+#include "Windows.h"
+#include "Args.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+static ColormapPtr InstalledMaps[MAXSCREENS];
+
+static Bool nxagentInstalledDefaultColormap = False;
+
+Bool nxagentReconnectAllColormap(void *p0);
+
+Bool nxagentCreateColormap(ColormapPtr pCmap)
+{
+ VisualPtr pVisual;
+ XColor *colors;
+ int i, ncolors;
+ Pixel red, green, blue;
+ Pixel redInc, greenInc, blueInc;
+
+ Visual *visual;
+ int class;
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "nxagentCreateColormap: Going to create new colormap with "
+ " visual [%lu].\n", pCmap->pVisual);
+ #endif
+
+ pVisual = pCmap->pVisual;
+ ncolors = pVisual->ColormapEntries;
+
+ pCmap->devPriv = (void *)malloc(sizeof(nxagentPrivColormap));
+
+ if (((visual = nxagentVisual(pVisual))) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateColormap: WARNING: Visual not found. Using default visual.\n");
+ #endif
+
+ visual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ class = nxagentVisuals[nxagentDefaultVisualIndex].class;
+ }
+ else
+ {
+ class = pVisual->class;
+ }
+
+
+ nxagentColormapPriv(pCmap)->colormap =
+ XCreateColormap(nxagentDisplay,
+ nxagentDefaultWindows[pCmap->pScreen->myNum],
+ visual,
+ (class & DynamicClass) ?
+ AllocAll : AllocNone);
+
+ switch (class) {
+ case StaticGray: /* read only */
+ colors = (XColor *)malloc(ncolors * sizeof(XColor));
+ for (i = 0; i < ncolors; i++)
+ colors[i].pixel = i;
+ XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors);
+ for (i = 0; i < ncolors; i++) {
+ pCmap->red[i].co.local.red = colors[i].red;
+ pCmap->red[i].co.local.green = colors[i].red;
+ pCmap->red[i].co.local.blue = colors[i].red;
+ }
+ free(colors);
+ break;
+
+ case StaticColor: /* read only */
+ colors = (XColor *)malloc(ncolors * sizeof(XColor));
+ for (i = 0; i < ncolors; i++)
+ colors[i].pixel = i;
+ XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors);
+ for (i = 0; i < ncolors; i++) {
+ pCmap->red[i].co.local.red = colors[i].red;
+ pCmap->red[i].co.local.green = colors[i].green;
+ pCmap->red[i].co.local.blue = colors[i].blue;
+ }
+ free(colors);
+ break;
+
+ case TrueColor: /* read only */
+ colors = (XColor *)malloc(ncolors * sizeof(XColor));
+ red = green = blue = 0L;
+ redInc = lowbit(pVisual->redMask);
+ greenInc = lowbit(pVisual->greenMask);
+ blueInc = lowbit(pVisual->blueMask);
+ for (i = 0; i < ncolors; i++) {
+ colors[i].pixel = red | green | blue;
+ red += redInc;
+ if (red > pVisual->redMask) red = 0L;
+ green += greenInc;
+ if (green > pVisual->greenMask) green = 0L;
+ blue += blueInc;
+ if (blue > pVisual->blueMask) blue = 0L;
+ }
+ XQueryColors(nxagentDisplay, nxagentColormap(pCmap), colors, ncolors);
+ for (i = 0; i < ncolors; i++) {
+ pCmap->red[i].co.local.red = colors[i].red;
+ pCmap->green[i].co.local.green = colors[i].green;
+ pCmap->blue[i].co.local.blue = colors[i].blue;
+ }
+ free(colors);
+ break;
+
+ case GrayScale: /* read and write */
+ break;
+
+ case PseudoColor: /* read and write */
+ break;
+
+ case DirectColor: /* read and write */
+ break;
+ }
+
+ return True;
+}
+
+void nxagentDestroyColormap(ColormapPtr pCmap)
+{
+ XFreeColormap(nxagentDisplay, nxagentColormap(pCmap));
+ free(pCmap->devPriv);
+}
+
+#define SEARCH_PREDICATE \
+ (nxagentWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i])
+
+static int nxagentCountInstalledColormapWindows(WindowPtr pWin, void * ptr)
+{
+ nxagentInstalledColormapWindows *icws = (nxagentInstalledColormapWindows *) ptr;
+
+ int i;
+
+ for (i = 0; i < icws->numCmapIDs; i++)
+ if (SEARCH_PREDICATE) {
+ icws->numWindows++;
+ return WT_DONTWALKCHILDREN;
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static int nxagentGetInstalledColormapWindows(WindowPtr pWin, void * ptr)
+{
+ nxagentInstalledColormapWindows *icws = (nxagentInstalledColormapWindows *)ptr;
+ int i;
+
+ for (i = 0; i < icws->numCmapIDs; i++)
+ if (SEARCH_PREDICATE) {
+ icws->windows[icws->index++] = nxagentWindow(pWin);
+ return WT_DONTWALKCHILDREN;
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static Window *nxagentOldInstalledColormapWindows = NULL;
+static int nxagentNumOldInstalledColormapWindows = 0;
+
+static Bool nxagentSameInstalledColormapWindows(Window *windows, int numWindows)
+{
+ if (nxagentNumOldInstalledColormapWindows != numWindows)
+ return False;
+
+ if (nxagentOldInstalledColormapWindows == windows)
+ return True;
+
+ if (nxagentOldInstalledColormapWindows == NULL || windows == NULL)
+ return False;
+
+ if (memcmp(nxagentOldInstalledColormapWindows, windows,
+ numWindows * sizeof(Window)))
+ return False;
+
+ return True;
+}
+
+void nxagentSetInstalledColormapWindows(ScreenPtr pScreen)
+{
+ nxagentInstalledColormapWindows icws;
+ int numWindows;
+
+ icws.cmapIDs = (Colormap *)malloc(pScreen->maxInstalledCmaps *
+ sizeof(Colormap));
+ icws.numCmapIDs = nxagentListInstalledColormaps(pScreen, icws.cmapIDs);
+ icws.numWindows = 0;
+ WalkTree(pScreen, nxagentCountInstalledColormapWindows, (void *)&icws);
+ if (icws.numWindows) {
+ icws.windows = (Window *)malloc((icws.numWindows + 1) * sizeof(Window));
+ icws.index = 0;
+ WalkTree(pScreen, nxagentGetInstalledColormapWindows, (void *)&icws);
+ icws.windows[icws.numWindows] = nxagentDefaultWindows[pScreen->myNum];
+ numWindows = icws.numWindows + 1;
+ }
+ else {
+ icws.windows = NULL;
+ numWindows = 0;
+ }
+
+ free(icws.cmapIDs);
+
+ if (!nxagentSameInstalledColormapWindows(icws.windows, icws.numWindows)) {
+ if (nxagentOldInstalledColormapWindows)
+ free(nxagentOldInstalledColormapWindows);
+
+#ifdef _XSERVER64
+ {
+ int i;
+ Window64 *windows = (Window64 *)malloc(numWindows * sizeof(Window64));
+
+ for(i = 0; i < numWindows; ++i)
+ windows[i] = icws.windows[i];
+ XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ windows, numWindows);
+ free(windows);
+ }
+#else
+ XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ icws.windows, numWindows);
+#endif
+
+ nxagentOldInstalledColormapWindows = icws.windows;
+ nxagentNumOldInstalledColormapWindows = icws.numWindows;
+
+#ifdef DUMB_WINDOW_MANAGERS
+ /*
+ This code is for dumb window managers.
+ This will only work with default local visual colormaps.
+ */
+ if (icws.numWindows)
+ {
+ WindowPtr pWin;
+ Visual *visual;
+ ColormapPtr pCmap;
+
+ pWin = nxagentWindowPtr(icws.windows[0]);
+ visual = nxagentVisualFromID(pScreen, wVisual(pWin));
+
+ if (visual == nxagentDefaultVisual(pScreen))
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin),
+ RT_COLORMAP);
+ else
+ pCmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
+ RT_COLORMAP);
+
+ if (pCmap != NULL)
+ {
+ XSetWindowColormap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentColormap(pCmap));
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "nxagentSetInstalledColormapWindows: WARNING! "
+ "Window at [%p] has no colormap with class [%d].\n",
+ (void *)pWin, pWin -> drawable.class);
+ }
+ #endif
+ }
+#endif /* DUMB_WINDOW_MANAGERS */
+ }
+ else
+ if (icws.windows) free(icws.windows);
+}
+
+void nxagentSetScreenSaverColormapWindow(ScreenPtr pScreen)
+{
+ if (nxagentOldInstalledColormapWindows)
+ free(nxagentOldInstalledColormapWindows);
+
+#ifdef _XSERVER64
+ {
+ Window64 window;
+
+ window = nxagentScreenSaverWindows[pScreen->myNum];
+ XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &window, 1);
+ nxagentScreenSaverWindows[pScreen->myNum] = window;
+ }
+#else
+ XSetWMColormapWindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &nxagentScreenSaverWindows[pScreen->myNum], 1);
+#endif /* _XSERVER64 */
+
+ nxagentOldInstalledColormapWindows = NULL;
+ nxagentNumOldInstalledColormapWindows = 0;
+
+ nxagentDirectUninstallColormaps(pScreen);
+}
+
+void nxagentDirectInstallColormaps(ScreenPtr pScreen)
+{
+ int i, n;
+ Colormap pCmapIDs[MAXCMAPS];
+
+ if (!nxagentDoDirectColormaps) return;
+
+ n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs);
+
+ for (i = 0; i < n; i++) {
+ ColormapPtr pCmap;
+
+ pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP);
+ if (pCmap)
+ XInstallColormap(nxagentDisplay, nxagentColormap(pCmap));
+ }
+}
+
+void nxagentDirectUninstallColormaps(ScreenPtr pScreen)
+{
+ int i, n;
+ Colormap pCmapIDs[MAXCMAPS];
+
+ if (!nxagentDoDirectColormaps) return;
+
+ n = (*pScreen->ListInstalledColormaps)(pScreen, pCmapIDs);
+
+ for (i = 0; i < n; i++) {
+ ColormapPtr pCmap;
+
+ pCmap = (ColormapPtr)LookupIDByType(pCmapIDs[i], RT_COLORMAP);
+ if (pCmap)
+ XUninstallColormap(nxagentDisplay, nxagentColormap(pCmap));
+ }
+}
+
+void nxagentInstallColormap(ColormapPtr pCmap)
+{
+ int index;
+ ColormapPtr pOldCmap;
+
+ index = pCmap->pScreen->myNum;
+ pOldCmap = InstalledMaps[index];
+
+ if(pCmap != pOldCmap)
+ {
+ nxagentDirectUninstallColormaps(pCmap->pScreen);
+
+ /* Uninstall pInstalledMap. Notify all interested parties. */
+ if(pOldCmap != (ColormapPtr)None)
+ WalkTree(pCmap->pScreen, TellLostMap, (void *)&pOldCmap->mid);
+
+ InstalledMaps[index] = pCmap;
+ WalkTree(pCmap->pScreen, TellGainedMap, (void *)&pCmap->mid);
+
+ nxagentSetInstalledColormapWindows(pCmap->pScreen);
+ nxagentDirectInstallColormaps(pCmap->pScreen);
+ }
+}
+
+void nxagentUninstallColormap(ColormapPtr pCmap)
+{
+ int index;
+ ColormapPtr pCurCmap;
+
+ index = pCmap->pScreen->myNum;
+ pCurCmap = InstalledMaps[index];
+
+ if(pCmap == pCurCmap)
+ {
+ if ((unsigned int)pCmap->mid != pCmap->pScreen->defColormap)
+ {
+ pCurCmap = (ColormapPtr)LookupIDByType(pCmap->pScreen->defColormap,
+ RT_COLORMAP);
+ (*pCmap->pScreen->InstallColormap)(pCurCmap);
+ }
+ }
+}
+
+int nxagentListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds)
+{
+ if (nxagentInstalledDefaultColormap)
+ {
+ *pCmapIds = InstalledMaps[pScreen->myNum]->mid;
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void nxagentStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors)
+{
+ if (pCmap->pVisual->class & DynamicClass)
+#ifdef _XSERVER64
+ {
+ int i;
+ XColor *pColors64 = (XColor *)malloc(nColors * sizeof(XColor) );
+
+ for(i = 0; i < nColors; ++i)
+ {
+ pColors64[i].pixel = pColors[i].pixel;
+ pColors64[i].red = pColors[i].red;
+ pColors64[i].green = pColors[i].green;
+ pColors64[i].blue = pColors[i].blue;
+ pColors64[i].flags = pColors[i].flags;
+ }
+ XStoreColors(nxagentDisplay, nxagentColormap(pCmap), pColors64, nColors);
+ free(pColors64);
+ }
+#else
+ XStoreColors(nxagentDisplay, nxagentColormap(pCmap),
+ (XColor *)pColors, nColors);
+#endif
+}
+
+void nxagentResolveColor(unsigned short *pRed, unsigned short *pGreen,
+ unsigned short *pBlue, VisualPtr pVisual)
+{
+ int shift;
+ unsigned int lim;
+
+ shift = 16 - pVisual->bitsPerRGBValue;
+ lim = (1 << pVisual->bitsPerRGBValue) - 1;
+
+ if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor))
+ {
+ /* rescale to rgb bits */
+ *pRed = ((*pRed >> shift) * 65535) / lim;
+ *pGreen = ((*pGreen >> shift) * 65535) / lim;
+ *pBlue = ((*pBlue >> shift) * 65535) / lim;
+ }
+ else if (pVisual->class == GrayScale)
+ {
+ /* rescale to gray then rgb bits */
+ *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
+ *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
+ }
+ else if (pVisual->class == StaticGray)
+ {
+ unsigned int limg;
+
+ limg = pVisual->ColormapEntries - 1;
+ /* rescale to gray then [0..limg] then [0..65535] then rgb bits */
+ *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
+ *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg;
+ *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
+ }
+ else
+ {
+ unsigned limr, limg, limb;
+
+ limr = pVisual->redMask >> pVisual->offsetRed;
+ limg = pVisual->greenMask >> pVisual->offsetGreen;
+ limb = pVisual->blueMask >> pVisual->offsetBlue;
+ /* rescale to [0..limN] then [0..65535] then rgb bits */
+ *pRed = ((((((*pRed * (limr + 1)) >> 16) *
+ 65535) / limr) >> shift) * 65535) / lim;
+ *pGreen = ((((((*pGreen * (limg + 1)) >> 16) *
+ 65535) / limg) >> shift) * 65535) / lim;
+ *pBlue = ((((((*pBlue * (limb + 1)) >> 16) *
+ 65535) / limb) >> shift) * 65535) / lim;
+ }
+}
+
+Bool nxagentCreateDefaultColormap(ScreenPtr pScreen)
+{
+ VisualPtr pVisual;
+ ColormapPtr pCmap;
+ unsigned short zero = 0, ones = 0xFFFF;
+ Pixel wp, bp;
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Searching for the root visual [%lu].\n",
+ pScreen->rootVisual);
+ #endif
+
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++);
+
+ if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap,
+ (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 0)
+ != Success)
+ return False;
+
+ wp = pScreen->whitePixel;
+ bp = pScreen->blackPixel;
+ if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) !=
+ Success) ||
+ (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) !=
+ Success))
+ return FALSE;
+ pScreen->whitePixel = wp;
+ pScreen->blackPixel = bp;
+ (*pScreen->InstallColormap)(pCmap);
+
+ nxagentInstalledDefaultColormap = True;
+
+ return True;
+}
+
+static void nxagentReconnectColormap(void * p0, XID x1, void * p2)
+{
+ ColormapPtr pCmap = (ColormapPtr)p0;
+ Bool* pBool = (Bool*)p2;
+ VisualPtr pVisual;
+
+ #ifdef NXAGENT_RECONNECT_COLORMAP_DEBUG
+ fprintf(stderr, "nxagentReconnectColormap: %p\n", pCmap);
+ #endif
+
+ if (!*pBool || !pCmap)
+ return;
+
+ pVisual = pCmap -> pVisual;
+
+ nxagentColormapPriv(pCmap)->colormap =
+ XCreateColormap(nxagentDisplay,
+ nxagentDefaultWindows[pCmap->pScreen->myNum],
+ nxagentVisual(pVisual),
+ (pVisual->class & DynamicClass) ?
+ AllocAll : AllocNone);
+
+ #ifdef NXAGENT_RECONNECT_COLORMAP_DEBUG
+ fprintf(stderr, "nxagentReconnectColormap: %p - ID %xl\n",
+ pCmap, nxagentColormap(pCmap));
+ #endif
+}
+
+Bool nxagentReconnectAllColormap(void *p0)
+{
+ int cid;
+ Bool success = True;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_COLORMAP_DEBUG)
+ fprintf(stderr, "nxagentReconnectAllColormap\n");
+ #endif
+
+ for (cid = 0; (cid < MAXCLIENTS) && success; cid++)
+ {
+ if (clients[cid] && success)
+ {
+ FindClientResourcesByType(clients[cid], RT_COLORMAP, nxagentReconnectColormap, &success);
+ }
+ }
+
+ return success;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Colormap.h b/nx-X11/programs/Xserver/hw/nxagent/Colormap.h
new file mode 100644
index 000000000..fc3c828f9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Colormap.h
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Color_H__
+#define __Color_H__
+
+#define DUMB_WINDOW_MANAGERS
+
+#define MAXCMAPS 1
+#define MINCMAPS 1
+
+typedef struct {
+ Colormap colormap;
+} nxagentPrivColormap;
+
+typedef struct {
+ int numCmapIDs;
+ Colormap *cmapIDs;
+ int numWindows;
+ Window *windows;
+ int index;
+} nxagentInstalledColormapWindows;
+
+#define nxagentColormapPriv(pCmap) \
+ ((nxagentPrivColormap *)((pCmap)->devPriv))
+
+#define nxagentColormap(pCmap) (nxagentColormapPriv(pCmap)->colormap)
+
+#define nxagentPixel(pixel) (pixel)
+
+Bool nxagentCreateColormap(ColormapPtr pCmap);
+
+void nxagentDestroyColormap(ColormapPtr pCmap);
+
+void nxagentSetInstalledColormapWindows(ScreenPtr pScreen);
+
+void nxagentSetScreenSaverColormapWindow(ScreenPtr pScreen);
+
+void nxagentDirectInstallColormaps(ScreenPtr pScreen);
+
+void nxagentDirectUninstallColormaps(ScreenPtr pScreen);
+
+void nxagentInstallColormap(ColormapPtr pCmap);
+
+void nxagentUninstallColormap(ColormapPtr pCmap);
+
+int nxagentListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds);
+
+void nxagentStoreColors(ColormapPtr pCmap, int nColors, xColorItem *pColors);
+
+void nxagentResolveColor(unsigned short *pRed, unsigned short *pGreen,
+ unsigned short *pBlue, VisualPtr pVisual);
+
+Bool nxagentCreateDefaultColormap(ScreenPtr pScreen);
+
+#endif /* __Color_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Composite.c b/nx-X11/programs/Xserver/hw/nxagent/Composite.c
new file mode 100644
index 000000000..bd84c52b0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.c
@@ -0,0 +1,207 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "scrnintstr.h"
+#include "windowstr.h"
+
+#include "Agent.h"
+#include "Screen.h"
+#include "Display.h"
+#include "Options.h"
+#include "Windows.h"
+
+#include "X11/include/Xcomposite_nxagent.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Set if the composite extension is supported
+ * by the remote display.
+ */
+
+int nxagentCompositeEnable = UNDEFINED;
+
+void nxagentCompositeExtensionInit()
+{
+ /*
+ * Set the flag only if the initialization
+ * completes.
+ */
+
+ nxagentCompositeEnable = 0;
+
+ if (nxagentOption(Composite) == 1)
+ {
+ int eventBase, errorBase;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCompositeExtensionInit: Checking if the composite extension is supported.\n");
+ #endif
+
+ if (XCompositeQueryExtension(nxagentDisplay, &eventBase, &errorBase) == 1)
+ {
+ /*
+ * At the moment we don't need to care
+ * the version of the extension.
+ */
+
+ #ifdef TEST
+
+ int major = -1;
+ int minor = -1;
+
+ XCompositeQueryVersion(nxagentDisplay, &major, &minor);
+
+ fprintf(stderr, "nxagentCompositeExtensionInit: The remote display supports version [%d] "
+ "minor [%d].\n", major, minor);
+
+ if (major < 0 || minor < 2)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCompositeExtensionInit: WARNING! Potentially incompatible version "
+ "[%d] minor [%d] detected.\n", major, minor);
+ #endif
+ }
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCompositeExtensionInit: Enabling the use of the composite extension.\n");
+ #endif
+
+ nxagentCompositeEnable = 1;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentCompositeExtensionInit: Composite extension not supported on this display.\n");
+ }
+ #endif
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentRenderExtensionInit: Use of the composite extension not enabled.\n");
+ }
+ #endif
+}
+
+void nxagentRedirectDefaultWindows()
+{
+ int i;
+
+ if (nxagentOption(Rootless) == 1 ||
+ nxagentCompositeEnable == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRedirectDefaultWindows: Not redirecting default "
+ "windows with rootless mode [%d] and composite [%d].\n",
+ nxagentOption(Rootless), nxagentCompositeEnable);
+ #endif
+
+ return;
+ }
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ WindowPtr pWin = screenInfo.screens[i]->root;
+
+ ScreenPtr pScreen = pWin -> drawable.pScreen;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRedirectDefaultWindows: WARNING! Redirecting default window id [%ld] "
+ "to off-screen memory.\n", (long int)nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+
+ /*
+ * When trying to redirect only the top level window,
+ * and not the subwindows, we incur in a strange be-
+ * haviour. The top level is unmapped, mapped, unmap-
+ * ped and then reparented. This at first makes the
+ * agent think that the window manager is gone, then
+ * the agent window disappears. To make thinks even
+ * more weird, this happens only at reconnection.
+ */
+
+ XCompositeRedirectSubwindows(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ CompositeRedirectAutomatic);
+ }
+}
+
+void nxagentRedirectWindow(WindowPtr pWin)
+{
+ if (nxagentOption(Rootless) == 0 ||
+ nxagentCompositeEnable == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRedirectWindow: Not redirecting window id [%ld] "
+ "to off-screen memory with rootless mode [%d] and composite [%d].\n",
+ nxagentWindow(pWin), nxagentOption(Rootless),
+ nxagentCompositeEnable);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRedirectWindow: WARNING! Redirecting window id [%ld] "
+ "to off-screen memory.\n", (long int)nxagentWindow(pWin));
+ #endif
+
+ XCompositeRedirectWindow(nxagentDisplay, nxagentWindow(pWin),
+ CompositeRedirectAutomatic);
+
+ nxagentWindowPriv(pWin) -> isRedirected = 1;
+}
+
+void nxagentUnredirectWindow(WindowPtr pWin)
+{
+ if (nxagentWindowPriv(pWin) -> isRedirected == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRedirectWindow: Disabling redirection of window id [%ld] "
+ "to off-screen memory.\n", nxagentWindow(pWin));
+ #endif
+
+ XCompositeUnredirectWindow(nxagentDisplay, nxagentWindow(pWin),
+ CompositeRedirectAutomatic);
+
+ nxagentWindowPriv(pWin) -> isRedirected = 0;
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "nxagentUnredirectWindow: WARNING! The window id [%ld] "
+ "was not redirected.\n", (long int)nxagentWindow(pWin));
+ }
+ #endif
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Composite.h b/nx-X11/programs/Xserver/hw/nxagent/Composite.h
new file mode 100644
index 000000000..abe2551bf
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Composite.h
@@ -0,0 +1,59 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Composite_H__
+#define __Composite_H__
+
+/*
+ * Set if the extension is present and
+ * its use is enabled.
+ */
+
+extern int nxagentCompositeEnable;
+
+/*
+ * Query the composite extension on the
+ * remote display and set the flag if
+ * it is supported.
+ */
+
+void nxagentCompositeExtensionInit(void);
+
+/*
+ * Let the X server redirect the window
+ * on the off-screen memory.
+ */
+
+void nxagentRedirectDefaultWindows(void);
+
+/*
+ * Enable or disabel the redirection of
+ * the given window.
+ */
+
+void nxagentRedirectWindow(WindowPtr pWin);
+void nxagentUnredirectWindow(WindowPtr pWin);
+
+#endif /* __Composite_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Cursor.c b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
new file mode 100644
index 000000000..1db26b7ec
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.c
@@ -0,0 +1,600 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "inputstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Options.h"
+#include "Screen.h"
+#include "Cursor.h"
+#include "Image.h"
+#include "Visual.h"
+#include "Keyboard.h"
+#include "Args.h"
+#include "Windows.h"
+#include "Events.h"
+#include "Render.h"
+#include "Client.h"
+
+#include "windowstr.h"
+#include "resource.h"
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Defined in Display.c. There are huge
+ * problems mixing the GC definition in
+ * Xlib with the server code. This must
+ * be reworked.
+ */
+
+extern XlibGC nxagentBitmapGC;
+
+/*
+ * From NXevents.c.
+ */
+
+extern CursorPtr GetSpriteCursor(void);
+
+void nxagentConstrainCursor(ScreenPtr pScreen, BoxPtr pBox)
+{
+ #ifdef TEST
+
+ int width, height;
+
+ width = nxagentOption(RootWidth);
+ height = nxagentOption(RootHeight);
+
+ if (pBox->x1 <= 0 && pBox->y1 <= 0 &&
+ pBox->x2 >= width && pBox->y2 >= height)
+ {
+ fprintf(stderr, "nxagentConstrainCursor: Called with box [%d,%d,%d,%d]. "
+ "Skipping the operation.\n", pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentConstrainCursor: WARNING! Called with box [%d,%d,%d,%d].\n",
+ pBox->x1, pBox->y1, pBox->x2, pBox->y2);
+ }
+
+ #endif
+}
+
+void nxagentCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox)
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+Bool nxagentDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+
+ /*
+ * Don't define the root cursor
+ * so that nxagent root window
+ * inherits the parent's cursor.
+ */
+
+ Cursor cursor;
+
+ cursor = (pCursor != rootCursor) ? nxagentCursor(pCursor, pScreen): None;
+
+ if (nxagentOption(Rootless) == False)
+ {
+ XDefineCursor(nxagentDisplay,
+ nxagentInputWindows[pScreen -> myNum],
+ cursor);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayCursor: Called for cursor at [%p] with private [%p].\n",
+ (void *) pCursor, pCursor->devPriv[pScreen->myNum]);
+ #endif
+ }
+
+ return True;
+}
+
+Bool nxagentRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ XImage *image;
+ Pixmap source, mask;
+ XColor fg_color, bg_color;
+ unsigned long valuemask;
+ XGCValues values;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRealizeCursor: Called for cursor at [%p].\n", (void *) pCursor);
+ #endif
+
+ valuemask = GCFunction |
+ GCPlaneMask |
+ GCForeground |
+ GCBackground |
+ GCClipMask;
+
+ values.function = GXcopy;
+ values.plane_mask = AllPlanes;
+ values.foreground = 1L;
+ values.background = 0L;
+ values.clip_mask = None;
+
+ XChangeGC(nxagentDisplay, nxagentBitmapGC, valuemask, &values);
+
+ source = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ mask = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ image = XCreateImage(nxagentDisplay,
+ nxagentDefaultVisual(pScreen),
+ 1, XYBitmap, 0,
+ (char *)pCursor->bits->source,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad(nxagentDisplay), 0);
+
+ /*
+ * If we used nxagentImageNormalize() here,
+ * we'd swap our own cursor data in place.
+ * Change byte_order and bitmap_bit_order
+ * in the image struct to let Xlib do the
+ * swap for us.
+ */
+
+ image -> byte_order = IMAGE_BYTE_ORDER;
+ image -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ NXCleanImage(image);
+
+ XPutImage(nxagentDisplay, source, nxagentBitmapGC, image,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree(image);
+
+ image = XCreateImage(nxagentDisplay,
+ nxagentDefaultVisual(pScreen),
+ 1, XYBitmap, 0,
+ (char *)pCursor->bits->mask,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad(nxagentDisplay), 0);
+
+ image -> byte_order = IMAGE_BYTE_ORDER;
+ image -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ NXCleanImage(image);
+
+ XPutImage(nxagentDisplay, mask, nxagentBitmapGC, image,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree(image);
+
+ fg_color.red = pCursor->foreRed;
+ fg_color.green = pCursor->foreGreen;
+ fg_color.blue = pCursor->foreBlue;
+
+ bg_color.red = pCursor->backRed;
+ bg_color.green = pCursor->backGreen;
+ bg_color.blue = pCursor->backBlue;
+
+ pCursor->devPriv[pScreen->myNum] = (void *) malloc(sizeof(nxagentPrivCursor));
+
+ nxagentCursorPriv(pCursor, pScreen)->cursor =
+ XCreatePixmapCursor(nxagentDisplay, source, mask, &fg_color,
+ &bg_color, pCursor->bits->xhot, pCursor->bits->yhot);
+
+ nxagentCursorUsesRender(pCursor, pScreen) = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRealizeCursor: Set cursor private at [%p] cursor is [%ld].\n",
+ (void *) nxagentCursorPriv(pCursor, pScreen),
+ nxagentCursorPriv(pCursor, pScreen) -> cursor);
+ #endif
+
+ XFreePixmap(nxagentDisplay, source);
+ XFreePixmap(nxagentDisplay, mask);
+
+ return True;
+}
+
+Bool nxagentUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ if (nxagentCursorUsesRender(pCursor, pScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, pScreen);
+
+ FreePicture(pPicture, pPicture -> id);
+ }
+
+ if (nxagentCursor(pCursor, pScreen) != None)
+ {
+ XFreeCursor(nxagentDisplay, nxagentCursor(pCursor, pScreen));
+
+ nxagentCursor(pCursor, pScreen) = None;
+ }
+
+ free(nxagentCursorPriv(pCursor, pScreen));
+
+ return True;
+}
+
+void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ Bool displayed)
+{
+ XColor fg_color, bg_color;
+
+ fg_color.red = pCursor->foreRed;
+ fg_color.green = pCursor->foreGreen;
+ fg_color.blue = pCursor->foreBlue;
+
+ bg_color.red = pCursor->backRed;
+ bg_color.green = pCursor->backGreen;
+ bg_color.blue = pCursor->backBlue;
+
+ XRecolorCursor(nxagentDisplay,
+ nxagentCursor(pCursor, pScreen),
+ &fg_color, &bg_color);
+}
+
+Bool (*nxagentSetCursorPositionW)(ScreenPtr pScreen, int x, int y,
+ Bool generateEvent);
+
+Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y,
+ Bool generateEvent)
+{
+ if (generateEvent != 0)
+ {
+ return (*nxagentSetCursorPositionW)(pScreen, x, y, generateEvent);
+ }
+ else
+ {
+ /*
+ * Calling miSetCursorPosition with generateEvent == 0
+ * causes a crash in miPoiterUpdate().
+ */
+
+ return 1;
+ }
+}
+
+void nxagentReconnectCursor(void * p0, XID x1, void * p2)
+{
+ Bool* pBool = (Bool*)p2;
+ CursorPtr pCursor = (CursorPtr) p0;
+
+ AnimCurPtr ac;
+ int j;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor);
+ #endif
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentReconnectCursor: pCursor at [%p]\n", pCursor);
+ #endif
+
+ if (!*pBool || !pCursor)
+ {
+ return;
+ }
+
+ if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0)
+ {
+ if (nxagentIsAnimCursor(pCursor))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor);
+ #endif
+
+ ac = nxagentGetAnimCursor(pCursor);
+
+ for (j = 0; j < ac->nelt; j++)
+ {
+ nxagentReconnectCursor (ac->elts[j].pCursor, x1, p2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor);
+ #endif
+ }
+ }
+ }
+
+ else
+ {
+ if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen);
+ int ret = 1;
+
+ nxagentReconnectPicture(pPicture, 0, &ret);
+
+ nxagentRenderRealizeCursor(nxagentDefaultScreen, pCursor);
+ }
+ else
+ {
+ free(nxagentCursorPriv(pCursor, nxagentDefaultScreen));
+ if (!nxagentRealizeCursor(nxagentDefaultScreen, pCursor))
+ {
+ fprintf(stderr, "nxagentReconnectCursor: nxagentRealizeCursor failed\n");
+ *pBool = False;
+ }
+ }
+ }
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentReconnectCursor: %p - ID %lx\n", pCursor, nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+}
+
+/*
+ * The parameter is ignored at the moment.
+ */
+
+void nxagentReDisplayCurrentCursor()
+{
+ CursorPtr pCursor = GetSpriteCursor();
+
+ if (pCursor &&
+ nxagentCursorPriv(pCursor, nxagentDefaultScreen) &&
+ nxagentCursor(pCursor, nxagentDefaultScreen))
+ {
+ nxagentDisplayCursor(nxagentDefaultScreen, pCursor);
+ }
+}
+
+Bool nxagentReconnectAllCursor(void *p0)
+{
+ int i;
+ Bool r = True;
+
+ GrabPtr grab = inputInfo.pointer -> grab;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_CURSOR_DEBUG)
+ fprintf(stderr, "nxagentReconnectAllCursor\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentReconnectCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentReconnectAllCursor: WARNING! Failed to recreate "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ if (grab)
+ {
+ nxagentReconnectCursor(grab -> cursor, 0, &r);
+ }
+
+ return r;
+}
+
+void nxagentDisconnectCursor(void * p0, XID x1, void * p2)
+{
+ Bool* pBool = (Bool *) p2;
+ CursorPtr pCursor = (CursorPtr) p0;
+
+ AnimCurPtr ac;
+ int j;
+
+ if (!*pBool || !pCursor)
+ {
+ return;
+ }
+
+ if (nxagentCursorPriv(pCursor, nxagentDefaultScreen) == 0)
+ {
+ if (nxagentIsAnimCursor(pCursor))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: nxagentIsAnimCursor pCursor at [%p]\n", pCursor);
+ #endif
+
+ ac = nxagentGetAnimCursor(pCursor);
+
+ for (j = 0; j < ac->nelt; j++)
+ {
+ nxagentDisconnectCursor (ac->elts[j].pCursor, x1, p2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Iteration [%d] pCursor at [%p]\n", j, ac->elts[j].pCursor);
+ #endif
+ }
+ }
+ return;
+ }
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentDisconnectCursor: %p - ID %lx\n",
+ pCursor,
+ nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Called with bool [%d].\n", *pBool);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Pointer to cursor is [%p] with counter [%d].\n",
+ (void *) pCursor, pCursor -> refcnt);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Dummy screen is at [%p].\n",
+ (void *) nxagentDefaultScreen);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Cursor private is at [%p].\n",
+ (void *) nxagentCursorPriv(pCursor, nxagentDefaultScreen));
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectCursor: Dummy screen number is [%d].\n",
+ nxagentDefaultScreen -> myNum);
+
+ fprintf(stderr, "nxagentDisconnectCursor: Cursor is [%ld].\n",
+ nxagentCursor(pCursor, nxagentDefaultScreen));
+ #endif
+
+ nxagentCursor(pCursor, nxagentDefaultScreen) = None;
+
+ if (nxagentCursorUsesRender(pCursor, nxagentDefaultScreen))
+ {
+ PicturePtr pPicture = nxagentCursorPicture(pCursor, nxagentDefaultScreen);
+ int ret = 1;
+
+ #if defined(NXAGENT_RECONNECT_CURSOR_DEBUG) || defined(NXAGENT_RECONNECT_PICTURE_DEBUG)
+ fprintf(stderr, "nxagentDisconnectCursor: disconnecting attached picture %p\n", pPicture);
+ #endif
+
+ nxagentDisconnectPicture(pPicture, 0, &ret);
+ }
+}
+
+Bool nxagentDisconnectAllCursor()
+{
+ int i;
+ Bool r = True;
+
+ GrabPtr grab = inputInfo.pointer -> grab;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllCursor: Going to iterate through cursor resources.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentDisconnectCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentDisconnectAllCursor: WARNING! Failed to disconnect "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ if (grab)
+ {
+ nxagentDisconnectCursor(grab -> cursor, 0, &r);
+ }
+
+ return r;
+}
+
+
+#ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+
+void nxagentPrintCursorInfo(CursorPtr pCursor, char msg[])
+{
+ fprintf(stderr, "%s: %p - ID %lx - ref count %d\n",
+ msg, pCursor, nxagentCursor(pCursor, nxagentDefaultScreen), pCursor->refcnt);
+}
+
+void nxagentListCursor(void *p0, void *p1, void *p2)
+{
+ CursorPtr pCursor = (CursorPtr)p0;
+
+ nxagentPrintCursorInfo(pCursor, "CursorDebug:");
+}
+
+void nxagentListCursors(void)
+{
+ int i;
+ Bool r;
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_CURSOR, nxagentListCursor, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentListCursors: WARNING! Failed to list "
+ "cursor for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+
+#endif /* NXAGENT_RECONNECT_CURSOR_DEBUG */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Cursor.h b/nx-X11/programs/Xserver/hw/nxagent/Cursor.h
new file mode 100644
index 000000000..b115dfa38
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Cursor.h
@@ -0,0 +1,117 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Cursor_H__
+#define __Cursor_H__
+
+#include "cursorstr.h"
+#include "picturestr.h"
+
+typedef struct {
+ Cursor cursor;
+ PicturePtr picture;
+ int uses_render;
+ int x;
+ int y;
+} nxagentPrivCursor;
+
+/*
+ * _AnimCurElt and _AnimCur already defined in animcur.c.
+ */
+
+typedef struct _AnimCurElt {
+ CursorPtr pCursor;
+ CARD32 delay;
+} AnimCurElt;
+
+typedef struct _AnimCur {
+ int nelt;
+ AnimCurElt *elts;
+} AnimCurRec, *AnimCurPtr;
+
+CursorBitsPtr nxagentAnimCursorBits;
+
+#define nxagentIsAnimCursor(c) ((c)->bits == nxagentAnimCursorBits)
+#define nxagentGetAnimCursor(c) ((AnimCurPtr) ((c) + 1))
+
+#define nxagentCursorPriv(pCursor, pScreen) \
+ ((nxagentPrivCursor *)((pCursor)->devPriv[pScreen->myNum]))
+
+#define nxagentCursor(pCursor, pScreen) \
+ (nxagentCursorPriv(pCursor, pScreen)->cursor)
+
+#define nxagentCursorPicture(pCursor, pScreen) \
+ (nxagentCursorPriv(pCursor, pScreen)->picture)
+
+#define nxagentCursorUsesRender(pCursor, pScreen) \
+ (nxagentCursorPriv(pCursor, pScreen)->uses_render)
+
+#define nxagentCursorXOffset(pCursor, pScreen) \
+ (nxagentCursorPriv(pCursor, pScreen)->x)
+
+#define nxagentCursorYOffset(pCursor, pScreen) \
+ (nxagentCursorPriv(pCursor, pScreen)->y)
+
+void nxagentConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
+
+void nxagentCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
+ BoxPtr pHotBox, BoxPtr pTopLeftBox);
+
+Bool nxagentDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
+
+Bool nxagentRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+
+Bool nxagentUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+
+void nxagentRecolorCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ Bool displayed);
+
+Bool nxagentSetCursorPosition(ScreenPtr pScreen, int x, int y,
+ Bool generateEvent);
+
+extern Bool (*nxagentSetCursorPositionW)(ScreenPtr pScreen, int x, int y,
+ Bool generateEvent);
+
+void nxagentDisconnectCursor(void * p0, XID x1, void * p2);
+void nxagentReconnectCursor(void * p0, XID x1, void * p2);
+void nxagentReDisplayCurrentCursor(void);
+Bool nxagentReconnectAllCursor(void *p0);
+Bool nxagentDisconnectAllCursor(void);
+
+#endif /* __Cursor_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.c b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c
new file mode 100644
index 000000000..b7852a0ac
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.c
@@ -0,0 +1,546 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "scrnintstr.h"
+#include "Agent.h"
+
+#include <nx-X11/Xlib.h>
+
+#include "opaque.h"
+
+#include "Args.h"
+#include "Display.h"
+#include "Dialog.h"
+
+#include <nx/NX.h>
+#include "compext/Compext.h"
+#include <nx/NXalert.h>
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+int nxagentKillDialogPid = 0;
+int nxagentSuspendDialogPid = 0;
+int nxagentRootlessDialogPid = 0;
+int nxagentPulldownDialogPid = 0;
+int nxagentFontsReplacementDialogPid = 0;
+int nxagentEnableRandRModeDialogPid = 0;
+int nxagentDisableRandRModeDialogPid = 0;
+int nxagentEnableDeferModePid = 0;
+int nxagentDisableDeferModePid = 0;
+
+static int nxagentFailedReconnectionDialogPid = 0;
+
+char nxagentPulldownWindow[16];
+
+char nxagentFailedReconnectionMessage[256];
+
+void nxagentResetDialog(int pid)
+{
+ if (pid == nxagentRootlessDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting rootless dialog pid [%d].\n", nxagentRootlessDialogPid);
+ #endif
+
+ nxagentRootlessDialogPid = 0;
+ }
+ else if (pid == nxagentPulldownDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting pulldown dialog pid [%d].\n", nxagentPulldownDialogPid);
+ #endif
+
+ nxagentPulldownDialogPid = 0;
+ }
+ else if (pid == nxagentFontsReplacementDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFontsReplacementDialog: Resetting fonts replacement dialog pid [%d].\n",
+ nxagentFontsReplacementDialogPid);
+ #endif
+
+ nxagentFontsReplacementDialogPid = 0;
+ }
+ else if (pid == nxagentKillDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting kill dialog pid [%d].\n", nxagentKillDialogPid);
+ #endif
+
+ nxagentKillDialogPid = 0;
+ }
+ else if (pid == nxagentSuspendDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting suspend dialog pid [%d].\n", nxagentSuspendDialogPid);
+ #endif
+
+ nxagentSuspendDialogPid = 0;
+ }
+ else if (pid == nxagentFailedReconnectionDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting Failed Reconnection dialog pid [%d].\n",
+ nxagentFailedReconnectionDialogPid);
+ #endif
+
+ nxagentFailedReconnectionDialogPid = 0;
+ }
+ else if (pid == nxagentEnableRandRModeDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting RandR mode dialog pid [%d].\n",
+ nxagentEnableRandRModeDialogPid);
+ #endif
+
+ nxagentEnableRandRModeDialogPid = 0;
+ }
+ else if (pid == nxagentDisableRandRModeDialogPid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting NoRandR mode dialog pid [%d].\n",
+ nxagentDisableRandRModeDialogPid);
+ #endif
+
+ nxagentDisableRandRModeDialogPid = 0;
+ }
+ else if (pid == nxagentEnableDeferModePid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting enable defer mode dialog pid [%d].\n",
+ nxagentEnableDeferModePid);
+ #endif
+
+ nxagentEnableDeferModePid = 0;
+ }
+ else if (pid == nxagentDisableDeferModePid)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetDialog: Resetting disable defer mode dialog pid [%d].\n",
+ nxagentDisableDeferModePid);
+ #endif
+
+ nxagentDisableDeferModePid = 0;
+ }
+}
+
+void nxagentLaunchDialog(DialogType dialogType)
+{
+ char dialogDisplay[256];
+ sigset_t set, oldSet;
+ int *pid;
+ char *type;
+ char *message;
+ int local;
+ const char *window = NULL;
+
+ switch (dialogType)
+ {
+ case DIALOG_KILL_SESSION:
+ {
+ message = DIALOG_KILL_SESSION_MESSAGE;
+ type = DIALOG_KILL_SESSION_TYPE;
+ local = DIALOG_KILL_SESSION_LOCAL;
+ pid = &nxagentKillDialogPid;
+
+ break;
+ }
+ case DIALOG_SUSPEND_SESSION:
+ {
+ message = DIALOG_SUSPEND_SESSION_MESSAGE;
+ type = DIALOG_SUSPEND_SESSION_TYPE;
+ local = DIALOG_SUSPEND_SESSION_LOCAL;
+ pid = &nxagentSuspendDialogPid;
+
+ break;
+ }
+ case DIALOG_ROOTLESS:
+ {
+ message = DIALOG_ROOTLESS_MESSAGE;
+ type = DIALOG_ROOTLESS_TYPE;
+ local = DIALOG_ROOTLESS_LOCAL;
+ pid = &nxagentRootlessDialogPid;
+
+ break;
+ }
+ case DIALOG_PULLDOWN:
+ {
+ message = DIALOG_PULLDOWN_MESSAGE;
+ type = DIALOG_PULLDOWN_TYPE;
+ local = DIALOG_PULLDOWN_LOCAL;
+ pid = &nxagentPulldownDialogPid;
+ window = nxagentPulldownWindow;
+
+ break;
+ }
+ case DIALOG_FONT_REPLACEMENT:
+ {
+ message = DIALOG_FONT_REPLACEMENT_MESSAGE;
+ type = DIALOG_FONT_REPLACEMENT_TYPE;
+ local = DIALOG_FONT_REPLACEMENT_LOCAL;
+ pid = &nxagentFontsReplacementDialogPid;
+
+ break;
+ }
+ case DIALOG_FAILED_RECONNECTION:
+ {
+ message = DIALOG_FAILED_RECONNECTION_MESSAGE;
+ type = DIALOG_FAILED_RECONNECTION_TYPE;
+ local = DIALOG_FAILED_RECONNECTION_LOCAL;
+ pid = &nxagentFailedReconnectionDialogPid;
+
+ break;
+ }
+ case DIALOG_ENABLE_DESKTOP_RESIZE_MODE:
+ {
+ message = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_MESSAGE;
+ type = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE;
+ local = DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL;
+ pid = &nxagentEnableRandRModeDialogPid;
+
+ break;
+ }
+ case DIALOG_DISABLE_DESKTOP_RESIZE_MODE:
+ {
+ message = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_MESSAGE;
+ type = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE;
+ local = DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL;
+ pid = &nxagentDisableRandRModeDialogPid;
+
+ break;
+ }
+ case DIALOG_ENABLE_DEFER_MODE:
+ {
+ message = DIALOG_ENABLE_DEFER_MODE_MESSAGE;
+ type = DIALOG_ENABLE_DEFER_MODE_TYPE;
+ local = DIALOG_ENABLE_DEFER_MODE_LOCAL;
+ pid = &nxagentEnableDeferModePid;
+
+ break;
+ }
+ case DIALOG_DISABLE_DEFER_MODE:
+ {
+ message = DIALOG_DISABLE_DEFER_MODE_MESSAGE;
+ type = DIALOG_DISABLE_DEFER_MODE_TYPE;
+ local = DIALOG_DISABLE_DEFER_MODE_LOCAL;
+ pid = &nxagentDisableDeferModePid;
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentLaunchDialog: Unknown Dialog type [%d].\n", dialogType);
+ #endif
+
+ return;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentLaunchDialog: Launching dialog type [%d] message [%s].\n", type, message);
+ #endif
+
+ if (dialogType == DIALOG_FAILED_RECONNECTION)
+ {
+ strncpy(dialogDisplay, nxagentDisplayName, 255);
+ }
+ else
+ {
+ strcpy(dialogDisplay, ":");
+ strncat(dialogDisplay, display, 254);
+ }
+
+ *(dialogDisplay + 255) = '\0';
+
+ /*
+ * We don't want to receive SIGCHLD
+ * before we store the child pid.
+ */
+
+ sigemptyset(&set);
+
+ sigaddset(&set, SIGCHLD);
+
+ sigprocmask(SIG_BLOCK, &set, &oldSet);
+
+ *pid = NXTransDialog(nxagentDialogName, message, window,
+ type, local, dialogDisplay);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentLaunchDialog: Launched dialog %s with pid [%d] on display %s.\n",
+ DECODE_DIALOG_TYPE(dialogType), *pid, dialogDisplay);
+ #endif
+
+ *dialogDisplay = '\0';
+
+ /*
+ * Restore the previous set of
+ * blocked signal.
+ */
+
+ sigprocmask(SIG_SETMASK, &oldSet, NULL);
+}
+
+void nxagentPulldownDialog(Window wid)
+{
+ snprintf(nxagentPulldownWindow, 15, "%ld", (long int) wid);
+ nxagentPulldownWindow[15] = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPulldownDialog: Going to launch pulldown "
+ "dialog on window [%s].\n", nxagentPulldownWindow);
+ #endif
+
+ nxagentLaunchDialog(DIALOG_PULLDOWN);
+
+ nxagentPulldownWindow[0] = 0;
+}
+
+void nxagentFailedReconnectionDialog(int alert, char *error)
+{
+ if (alert == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFailedReconnectionDialog: WARNING! No valid alert provided. "
+ "Using the default.\n");
+ #endif
+
+ alert = FAILED_RESUME_DISPLAY_ALERT;
+ }
+
+ if (NXDisplayError(nxagentDisplay) == 0 &&
+ NXTransRunning(NX_FD_ANY) == 1)
+ {
+ NXTransAlert(alert, NX_ALERT_REMOTE);
+
+ /*
+ * Make it possible to interrupt the
+ * loop with a signal.
+ */
+
+ while (NXDisplayError(nxagentDisplay) == 0 &&
+ NXTransRunning(NX_FD_ANY) == 1)
+ {
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ NXTransContinue(&timeout);
+ }
+ }
+ else
+ {
+ int pid;
+ int status;
+ int options = 0;
+
+ snprintf(nxagentFailedReconnectionMessage, 255, "Reconnection failed: %s", error);
+
+ *(nxagentFailedReconnectionMessage + 255) = '\0';
+
+ nxagentLaunchDialog(DIALOG_FAILED_RECONNECTION);
+
+ while ((pid = waitpid(nxagentFailedReconnectionDialogPid, &status, options)) == -1 &&
+ errno == EINTR);
+
+ if (pid == -1)
+ {
+ if (errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFailedReconnectionDialog: Got ECHILD waiting for child [%d].\n",
+ nxagentFailedReconnectionDialogPid);
+ #endif
+
+ nxagentFailedReconnectionDialogPid = 0;
+ }
+ else
+ {
+ fprintf(stderr, "nxagentFailedReconnectionDialog: PANIC! Got unexpected error [%s] waiting "
+ "for child [%d].\n", strerror(errno), nxagentFailedReconnectionDialogPid);
+ }
+ }
+ else if (pid > 0)
+ {
+ if (WIFSTOPPED(status))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] was stopped "
+ "with signal [%d].\n", pid, (WSTOPSIG(status)));
+ #endif
+ }
+ else
+ {
+ #ifdef WARNING
+
+ if (WIFEXITED(status))
+ {
+ fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] exited "
+ "with status [%d].\n", pid, (WEXITSTATUS(status)));
+ }
+ else if (WIFSIGNALED(status))
+ {
+ fprintf(stderr, "nxagentFailedReconnectionDialog: Child process [%d] died "
+ "because of signal [%d].\n", pid, (WTERMSIG(status)));
+ }
+
+ #endif
+
+ nxagentResetDialog(pid);
+ }
+ }
+ #ifdef WARNING
+ else if (pid == 0)
+ {
+ fprintf(stderr, "nxagentFailedReconnectionDialog: No own child process exited.\n");
+ }
+ #endif
+ }
+}
+
+void nxagentTerminateDialog(DialogType type)
+{
+ int pid;
+
+ switch (type)
+ {
+ case DIALOG_KILL_SESSION:
+ {
+ pid = nxagentKillDialogPid;
+
+ break;
+ }
+ case DIALOG_SUSPEND_SESSION:
+ {
+ pid = nxagentSuspendDialogPid;
+
+ break;
+ }
+ case DIALOG_ROOTLESS:
+ {
+ pid = nxagentRootlessDialogPid;
+
+ break;
+ }
+ case DIALOG_PULLDOWN:
+ {
+ pid = nxagentPulldownDialogPid;
+
+ break;
+ }
+ case DIALOG_FONT_REPLACEMENT:
+ {
+ pid = nxagentFontsReplacementDialogPid;
+
+ break;
+ }
+ case DIALOG_FAILED_RECONNECTION:
+ {
+ pid = nxagentFailedReconnectionDialogPid;
+
+ break;
+ }
+ case DIALOG_ENABLE_DESKTOP_RESIZE_MODE:
+ {
+ pid = nxagentEnableRandRModeDialogPid;
+
+ break;
+ }
+ case DIALOG_DISABLE_DESKTOP_RESIZE_MODE:
+ {
+ pid = nxagentDisableRandRModeDialogPid;
+
+ break;
+ }
+ case DIALOG_ENABLE_DEFER_MODE:
+ {
+ pid = nxagentEnableDeferModePid;
+
+ break;
+ }
+ case DIALOG_DISABLE_DEFER_MODE:
+ {
+ pid = nxagentDisableDeferModePid;
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentTerminateDialog: Unknown dialog type [%d].\n", type);
+ #endif
+
+ return;
+ }
+ }
+
+ if (pid > 0)
+ {
+ if (kill(pid, SIGTERM) == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentTerminateDialog: Failed to terminate dialog pid [%d]: %s.\n",
+ pid, strerror(errno));
+ #endif
+ }
+ }
+ #ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "nxagentTerminateDialog: Dialog type [%d] is not running.\n",
+ type);
+ }
+ #endif
+}
+
+void nxagentTerminateDialogs()
+{
+ DialogType type;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTerminateDialogs: Terminating all the running dialogs.\n");
+ #endif
+
+ for (type = DIALOG_FIRST_TAG; type < DIALOG_LAST_TAG; type++)
+ {
+ nxagentTerminateDialog(type);
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Dialog.h b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h
new file mode 100644
index 000000000..133dee242
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Dialog.h
@@ -0,0 +1,216 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Dialog_H__
+#define __Dialog_H__
+
+#include "X11/X.h"
+
+typedef enum
+{
+ DIALOG_FIRST_TAG,
+ DIALOG_KILL_SESSION = DIALOG_FIRST_TAG,
+ DIALOG_SUSPEND_SESSION,
+ DIALOG_ROOTLESS,
+ DIALOG_PULLDOWN,
+ DIALOG_FONT_REPLACEMENT,
+ DIALOG_ENABLE_DESKTOP_RESIZE_MODE,
+ DIALOG_DISABLE_DESKTOP_RESIZE_MODE,
+ DIALOG_FAILED_RECONNECTION,
+ DIALOG_ENABLE_DEFER_MODE,
+ DIALOG_DISABLE_DEFER_MODE,
+ DIALOG_LAST_TAG
+
+} DialogType;
+
+extern int nxagentKillDialogPid;
+extern int nxagentSuspendDialogPid;
+extern int nxagentRootlessDialogPid;
+extern int nxagentPulldownDialogPid;
+extern int nxagentFontsReplacementDialogPid;
+extern int nxagentEnableRandRModeDialogPid;
+extern int nxagentDisableRandRModeDialogPid;
+extern int nxagentEnableDeferModePid;
+extern int nxagentDisableDeferModePid;
+
+extern char nxagentFailedReconnectionMessage[];
+
+extern char nxagentPulldownWindow[];
+
+extern void nxagentLaunchDialog(DialogType type);
+extern void nxagentResetDialog(int pid);
+extern void nxagentTerminateDialog(DialogType type);
+extern void nxagentFailedReconnectionDialog(int alert, char *error);
+extern void nxagentPulldownDialog(Window);
+extern void nxagentTerminateDialogs(void);
+
+#define nxagentNoDialogIsRunning \
+ (nxagentSuspendDialogPid == 0 && \
+ nxagentKillDialogPid == 0 && \
+ nxagentEnableRandRModeDialogPid == 0 && \
+ nxagentDisableRandRModeDialogPid == 0 && \
+ nxagentEnableDeferModePid == 0 && \
+ nxagentDisableDeferModePid == 0)
+
+#define DECODE_DIALOG_TYPE(type) \
+ ((type) == DIALOG_KILL_SESSION ? "DIALOG_KILL_SESSION" : \
+ (type) == DIALOG_SUSPEND_SESSION ? "DIALOG_SUSPEND_SESSION" : \
+ (type) == DIALOG_ROOTLESS ? "DIALOG_ROOTLESS" : \
+ (type) == DIALOG_PULLDOWN ? "DIALOG_PULLDOWN" : \
+ (type) == DIALOG_FONT_REPLACEMENT ? "DIALOG_FONT_REPLACEMENT" : \
+ (type) == DIALOG_ENABLE_DESKTOP_RESIZE_MODE ? "DIALOG_ENABLE_DESKTOP_RESIZE_MODE" :\
+ (type) == DIALOG_DISABLE_DESKTOP_RESIZE_MODE ? "DIALOG_DISABLE_DESKTOP_RESIZE_MODE" :\
+ (type) == DIALOG_FAILED_RECONNECTION ? "DIALOG_FAILED_RECONNECTION" : \
+ (type) == DIALOG_ENABLE_DEFER_MODE ? "DIALOG_ENABLE_DEFER_MODE" : \
+ (type) == DIALOG_DISABLE_DEFER_MODE ? "DIALOG_DISABLE_DEFER_MODE" : \
+ "UNKNOWN_DIALOG")
+
+/*
+ * Message to be showed to users when the close
+ * button is pressed. The right message is chosen
+ * according if session does or does not run in
+ * persistent mode.
+ */
+
+#define DIALOG_KILL_SESSION_MESSAGE \
+\
+"\
+Do you really want to close the session?\
+"
+
+#define DIALOG_KILL_SESSION_TYPE "yesno"
+
+#define DIALOG_KILL_SESSION_LOCAL 0
+
+
+#define DIALOG_SUSPEND_SESSION_MESSAGE \
+\
+"\
+Press the disconnect button to disconnect the running session.\n\
+You will be able to resume the session at later time. Press the\n\
+terminate button to exit the session and close all the running\n\
+programs.\
+"
+
+#define DIALOG_SUSPEND_SESSION_TYPE "yesnosuspend"
+
+#define DIALOG_SUSPEND_SESSION_LOCAL 0
+
+
+#define DIALOG_ROOTLESS_MESSAGE \
+\
+"\
+All remote applications have been terminated.\n\
+Do you want to close the session?\
+"
+
+#define DIALOG_ROOTLESS_TYPE "yesno"
+
+#define DIALOG_ROOTLESS_LOCAL 0
+
+
+#define DIALOG_PULLDOWN_MESSAGE \
+\
+nxagentPulldownWindow
+
+#define DIALOG_PULLDOWN_TYPE "pulldown"
+
+#define DIALOG_PULLDOWN_LOCAL 0
+
+
+#define DIALOG_FONT_REPLACEMENT_MESSAGE \
+\
+"\
+Unable to retrieve all the fonts currently in use. \n\
+Missing fonts have been replaced.\
+"
+
+#define DIALOG_FONT_REPLACEMENT_TYPE "ok"
+
+#define DIALOG_FONT_REPLACEMENT_LOCAL 0
+
+
+#define DIALOG_FAILED_RECONNECTION_MESSAGE \
+\
+nxagentFailedReconnectionMessage
+
+#define DIALOG_FAILED_RECONNECTION_TYPE "ok"
+
+#define DIALOG_FAILED_RECONNECTION_LOCAL 0
+
+
+#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_MESSAGE \
+\
+"\
+The session is now running in desktop resize mode.\n\
+You can resize the desktop by simply dragging the\n\
+desktop window's border. You can press Ctrl+Alt+R\n\
+again to disable this option.\
+"
+
+#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_TYPE "ok"
+
+#define DIALOG_ENABLE_DESKTOP_RESIZE_MODE_LOCAL 0
+
+#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_MESSAGE \
+\
+"\
+The session is now running in viewport mode. You can\n\
+navigate across different areas of the desktop window\n\
+by dragging the desktop with the mouse or by using the\n\
+arrows keys while pressing Ctrl+Alt. Press Ctrl+Alt+R\n\
+again to return to the desktop resize mode.\
+"
+
+#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_TYPE "ok"
+
+#define DIALOG_DISABLE_DESKTOP_RESIZE_MODE_LOCAL 0
+
+
+#define DIALOG_ENABLE_DEFER_MODE_MESSAGE \
+\
+"\
+Deferred screen updates are now enabled. You can press\n\
+Ctrl+Alt+E again to disable this option.\
+"
+
+#define DIALOG_ENABLE_DEFER_MODE_TYPE "ok"
+
+#define DIALOG_ENABLE_DEFER_MODE_LOCAL 0
+
+
+#define DIALOG_DISABLE_DEFER_MODE_MESSAGE \
+\
+"\
+Deferred screen updates are now disabled. You can press\n\
+Ctrl+Alt+E to enable it again.\
+"
+
+#define DIALOG_DISABLE_DEFER_MODE_TYPE "ok"
+
+#define DIALOG_DISABLE_DEFER_MODE_LOCAL 0
+
+#endif /* __Dialog_H__ */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.c b/nx-X11/programs/Xserver/hw/nxagent/Display.c
new file mode 100644
index 000000000..c764f50ae
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Display.c
@@ -0,0 +1,2963 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+
+#ifdef WATCH
+#include "unistd.h"
+#endif
+
+#include <nx/NXalert.h>
+
+#include "Agent.h"
+#include "Display.h"
+#include "Visual.h"
+#include "Options.h"
+#include "Error.h"
+#include "Init.h"
+#include "Args.h"
+#include "Image.h"
+
+#define Pixmap XlibPixmap
+#include "Icons.h"
+#undef Pixmap
+
+#include "Render.h"
+#include "Font.h"
+#include "Reconnect.h"
+#include "Events.h"
+#include "Dialog.h"
+#include "Client.h"
+#include "Splash.h"
+#include "Screen.h"
+#include "Handlers.h"
+
+#include <nx/NX.h>
+#include "compext/Compext.h"
+
+#include NXAGENT_ICON_NAME
+#include X2GOAGENT_ICON_NAME
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+
+Display *nxagentDisplay = NULL;
+XVisualInfo *nxagentVisuals = NULL;
+Bool nxagentTrue24 = False;
+
+int nxagentNumVisuals;
+int nxagentXConnectionNumber;
+
+int nxagentIOErrorHandler(Display *display);
+
+static Bool nxagentDisplayInfoSaved = False;
+static Display *nxagentDisplayBackup = NULL;
+static XlibGC nxagentBitmapGCBackup = NULL;
+static XVisualInfo *nxagentVisualsRecBackup;
+static int nxagentNumVisualsRecBackup;
+static int nxagentNumDefaultColormapsRecBackup;
+static int *nxagentDepthsRecBackup;
+static int nxagentNumDepthsRecBackup;
+static int nxagentDefaultDepthRecBackup;
+static int nxagentDisplayWidthRecBackup;
+static int nxagentDisplayHeightRecBackup;
+static Bool nxagentRenderEnableRecBackup;
+static Bool *nxagentVisualHasBeenIgnored;
+
+static enum
+{
+ NOTHING = 0,
+ OPENED,
+ GOT_VISUAL_INFO,
+ ALLOC_DEF_COLORMAP,
+ GOT_DEPTH_LIST,
+ GOT_PIXMAP_FORMAT_LIST,
+ EVERYTHING_DONE
+} reconnectDisplayState;
+
+int nxagentDefaultVisualIndex;
+Colormap *nxagentDefaultColormaps = NULL;
+int nxagentNumDefaultColormaps;
+int *nxagentDepths = NULL;
+int nxagentNumDepths;
+XPixmapFormatValues *nxagentPixmapFormats = NULL;
+XPixmapFormatValues *nxagentRemotePixmapFormats = NULL;
+int nxagentNumPixmapFormats;
+int nxagentRemoteNumPixmapFormats;
+Pixel nxagentBlackPixel;
+Pixel nxagentWhitePixel;
+Drawable nxagentDefaultDrawables[MAXDEPTH + 1];
+Pixmap nxagentScreenSaverPixmap;
+
+/*
+ * Also used in Cursor.c. There are huge problems
+ * using GC definition. This is to be reworked.
+ */
+
+XlibGC nxagentBitmapGC;
+
+/*
+ * The "confine" window is used in the nxagentConstrainCursor
+ * procedure. We are currently overriding the original Xnest
+ * behaviour. It is unclear what this window is used for.
+ */
+
+Window nxagentConfineWindow;
+
+Pixmap nxagentIconPixmap;
+Pixmap nxagentIconShape;
+Bool useXpmIcon = False;
+
+Bool nxagentMakeIcon(Display *display, Pixmap *nxIcon, Pixmap *nxMask);
+
+
+static void nxagentInitVisuals(void);
+static void nxagentSetDefaultVisual(void);
+static void nxagentInitDepths(void);
+static void nxagentInitPixmapFormats(void);
+
+static int nxagentCheckForDefaultDepthCompatibility(void);
+static int nxagentCheckForDepthsCompatibility(void);
+static int nxagentCheckForPixmapFormatsCompatibility(void);
+static int nxagentInitAndCheckVisuals(int flexibility);
+static int nxagentCheckForColormapsCompatibility(int flexibility);
+
+/*
+ * Save Internal implementation Also called in Reconnect.c.
+ */
+
+Display *nxagentInternalOpenDisplay(char *display);
+
+#ifdef NXAGENT_TIMESTAMP
+unsigned long startTime;
+#endif
+
+/*
+ * This is located in connection.c.
+ */
+
+extern void RejectWellKnownSockets(void);
+
+int nxagentServerOrder()
+{
+ int whichbyte = 1;
+
+ if (*((char *) &whichbyte))
+ return LSBFirst;
+
+ return MSBFirst;
+}
+
+/*
+ * FIXME: This error handler is not printing anything
+ * in the session log. This is OK once the session is
+ * started, because the error is handled by the other
+ * layers, but not before that point, as the agent
+ * would die without giving any feedback to the user
+ * (or, worse, to the NX server). We should check how
+ * many requests have been handled for this display
+ * and print a message if the display dies before the
+ * session is up and running.
+ */
+
+/*
+ * FIXME: This should be moved to Error.c, The other
+ * handlers should be probably moved to Handlers.c.
+ */
+
+int nxagentIOErrorHandler(Display *display)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentIOErrorHandler: Got I/O error with nxagentException.ioError [%d].\n",
+ nxagentException.ioError);
+ #endif
+
+ nxagentException.ioError++;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentIOErrorHandler: Set nxagentException.ioError to [%d].\n",
+ nxagentException.ioError);
+ #endif
+
+ return 1;
+}
+
+/*
+ * Force a shutdown of any connection attempt
+ * while connecting to the remote display.
+ * This is needed to avoid a hang up in case
+ * of loopback connections to our own listen-
+ * ing sockets.
+ */
+
+static void nxagentRejectConnection(int signal)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentRejectConnection: Going to reject client connections.\n");
+ #endif
+
+ RejectWellKnownSockets();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRejectConnection: Setting new alarm to 5 seconds from now.\n");
+ #endif
+
+ /*
+ * A further timeout is unlikely to happen
+ * in the case of loopback connections.
+ */
+
+ alarm(5);
+}
+
+/*
+ * Ignore the signal if the NX transport is
+ * not running.
+ */
+
+static void nxagentSigusrHandler(int signal)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSigusrHandler: Nothing to do with signal [%d].\n",
+ signal);
+ #endif
+}
+
+static void nxagentSighupHandler(int signal)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Handling signal with state [%s] transport [%d] server "
+ "generation [%ld].\n", DECODE_SESSION_STATE(nxagentSessionState),
+ NXTransRunning(NX_FD_ANY), serverGeneration);
+ #endif
+
+ if (signal != SIGHUP)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSighupHandler: PANIC! Invalid signal [%d] received in state [%s].\n",
+ signal, DECODE_SESSION_STATE(nxagentSessionState));
+ #endif
+
+ return;
+ }
+
+ if (dispatchException & DE_TERMINATE)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Ignoring the signal while terminating the session.\n");
+ #endif
+
+ return;
+ }
+ else if (nxagentSessionState == SESSION_UP)
+ {
+ if (nxagentOption(Persistent) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Handling the signal by disconnecting the agent.\n");
+ #endif
+
+ nxagentException.sigHup++;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Ignoring the signal with persistency disabled.\n");
+ #endif
+ }
+
+ return;
+ }
+ else if (nxagentSessionState == SESSION_STARTING)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Handling the signal by aborting the session.\n");
+ #endif
+
+ nxagentException.sigHup++;
+
+ return;
+ }
+ else if (nxagentSessionState == SESSION_DOWN)
+ {
+ if (NXTransRunning(NX_FD_ANY) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Handling the signal by aborting the reconnection.\n");
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSighupHandler: Handling the signal by resuming the session.\n");
+ #endif
+ }
+
+ nxagentException.sigHup++;
+
+ return;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSighupHandler: WARNING! Ignoring the signal in state [%s].\n",
+ DECODE_SESSION_STATE(nxagentSessionState));
+ #endif
+}
+
+static void nxagentSigchldHandler(int signal)
+{
+ int pid = 0;
+ int status;
+ int options;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSigchldHandler: Going to check the children processes.\n");
+ #endif
+
+ options = WNOHANG | WUNTRACED;
+
+ /*
+ * Try with the pid of the dialog process.
+ * Leave the other children unaffected.
+ */
+
+ if (nxagentRootlessDialogPid)
+ {
+ pid = waitpid(nxagentRootlessDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Rootless dialog).\n",
+ nxagentRootlessDialogPid);
+ #endif
+
+ pid = nxagentRootlessDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentPulldownDialogPid)
+ {
+ pid = waitpid(nxagentPulldownDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Pulldown dialog).\n",
+ nxagentPulldownDialogPid);
+ #endif
+
+ pid = nxagentPulldownDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentKillDialogPid)
+ {
+ pid = waitpid(nxagentKillDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Kill dialog).\n",
+ nxagentKillDialogPid);
+ #endif
+
+ pid = nxagentKillDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentSuspendDialogPid)
+ {
+ pid = waitpid(nxagentSuspendDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Suspend dialog).\n",
+ nxagentSuspendDialogPid);
+ #endif
+
+ pid = nxagentSuspendDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentFontsReplacementDialogPid)
+ {
+ pid = waitpid(nxagentFontsReplacementDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (Fonts replacement).\n",
+ nxagentFontsReplacementDialogPid);
+ #endif
+
+ pid = nxagentFontsReplacementDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentEnableRandRModeDialogPid)
+ {
+ pid = waitpid(nxagentEnableRandRModeDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (EnableRandRMode dialog).\n",
+ nxagentEnableRandRModeDialogPid);
+ #endif
+
+ pid = nxagentEnableRandRModeDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentDisableRandRModeDialogPid)
+ {
+ pid = waitpid(nxagentDisableRandRModeDialogPid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (DisableRandRMode dialog).\n",
+ nxagentDisableRandRModeDialogPid);
+ #endif
+
+ pid = nxagentDisableRandRModeDialogPid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentEnableDeferModePid)
+ {
+ pid = waitpid(nxagentEnableDeferModePid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (EnableDeferMode dialog).\n",
+ nxagentEnableDeferModePid);
+ #endif
+
+ pid = nxagentEnableDeferModePid = 0;
+ }
+ }
+
+ if (pid == 0 && nxagentDisableDeferModePid)
+ {
+ pid = waitpid(nxagentDisableDeferModePid, &status, options);
+
+ if (pid == -1 && errno == ECHILD)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Got ECHILD waiting for child %d (DisableDeferMode dialog).\n",
+ nxagentDisableDeferModePid);
+ #endif
+
+ pid = nxagentDisableDeferModePid = 0;
+ }
+ }
+
+ if (pid == -1)
+ {
+ FatalError("Got error '%s' waiting for the child.\n", strerror(errno));
+ }
+
+ if (pid > 0)
+ {
+ if (WIFSTOPPED(status))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSigchldHandler: Child process [%d] was stopped "
+ "with signal [%d].\n", pid, (WSTOPSIG(status)));
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+
+ if (WIFEXITED(status))
+ {
+ fprintf(stderr, "nxagentSigchldHandler: Child process [%d] exited "
+ "with status [%d].\n", pid, (WEXITSTATUS(status)));
+ }
+ else if (WIFSIGNALED(status))
+ {
+ fprintf(stderr, "nxagentSigchldHandler: Child process [%d] died "
+ "because of signal [%d].\n", pid, (WTERMSIG(status)));
+ }
+
+ #endif
+
+ nxagentResetDialog(pid);
+ }
+ }
+ else if (pid == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSigchldHandler: Forwarding the signal to the NX transport.\n");
+ #endif
+
+ NXTransSignal(SIGCHLD, NX_SIGNAL_RAISE);
+ }
+
+ return;
+}
+
+Display *nxagentInternalOpenDisplay(char *display)
+{
+ Display *newDisplay;
+
+ struct sigaction oldAction;
+ struct sigaction newAction;
+
+ int result;
+
+ /*
+ * Stop the smart schedule timer since
+ * it uses SIGALRM as we do.
+ */
+
+ nxagentStopTimer();
+
+ /*
+ * Install the handler rejecting a possible
+ * loopback connection.
+ */
+/*
+FIXME: Should print a warning if the user tries to let
+ the agent impersonate the same display as the
+ display where the agent is supposed to connect.
+ We actually handle this by means of RejectWell-
+ KnownSockets() but without giving to the user
+ a friendly explaination for the error.
+*/
+
+ newAction.sa_handler = nxagentRejectConnection;
+
+ sigfillset(&newAction.sa_mask);
+
+ newAction.sa_flags = 0;
+
+ while (((result = sigaction(SIGALRM, &newAction,
+ &oldAction)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set alarm for rejecting connections.");
+ }
+
+ alarm(10);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInternalOpenDisplay: Going to open the display [%s].\n",
+ display);
+ #endif
+
+ newDisplay = XOpenDisplay(display);
+
+ alarm(0);
+
+ while (((result = sigaction(SIGALRM, &oldAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't restore alarm for rejecting connections.");
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInternalOpenDisplay: Setting the NX flush policy to immediate.\n");
+ #endif
+
+ NXSetDisplayPolicy(nxagentDisplay, NXPolicyImmediate);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInternalOpenDisplay: Function returned display at [%p].\n",
+ (void *) newDisplay);
+ #endif
+
+ return newDisplay;
+}
+
+static void nxagentDisplayBlockHandler(Display *display, int reason)
+{
+ if (nxagentDisplay != NULL)
+ {
+ /*
+ * Don't allow the smart schedule to
+ * interrupt the agent while waiting
+ * for the remote display.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Stopping the smart schedule timer.\n");
+ #endif
+
+ nxagentStopTimer();
+
+ if (reason == NXBlockRead)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Display is blocking for [read].\n");
+ #endif
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Display is blocking for [write].\n");
+ #endif
+
+ nxagentBlocking = 1;
+
+ if (!SmartScheduleSignalEnable)
+ {
+
+ /*
+ * Let the dispatch attend the next
+ * client.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisplayBlockHandler: BLOCK! Yielding with agent blocked.\n");
+ #endif
+
+ nxagentDispatch.start = GetTimeInMillis();
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+
+ }
+
+ /*
+ * Give a chance to the next client.
+ */
+
+ isItTimeToYield = 1;
+ }
+ }
+}
+
+static void nxagentDisplayWriteHandler(Display *display, int length)
+{
+ if (nxagentDisplay != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayWriteHandler: WRITE! Called with [%d] bytes written.\n",
+ length);
+ #endif
+
+ /*
+ * Notify the dispatch handler.
+ */
+
+ nxagentDispatchHandler(NULL, 0, length);
+
+ if (nxagentOption(LinkType) == LINK_TYPE_NONE)
+ {
+ nxagentFlush = GetTimeInMillis();
+ }
+ }
+}
+
+static CARD32 nxagentRateTime = 5000;
+static CARD32 nxagentLastTime;
+static unsigned int nxagentRate = 0;
+
+int nxagentGetDataRate(void)
+{
+ return nxagentRate;
+}
+
+static void nxagentDisplayFlushHandler(Display *display, int length)
+{
+ CARD32 time;
+
+ if (nxagentDisplay != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayFlushHandler: FLUSH! Called with [%d] bytes flushed.\n",
+ length);
+ #endif
+
+ nxagentCongestion = NXDisplayCongestion(nxagentDisplay);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayFlushHandler: FLUSH! Current congestion level is [%d].\n",
+ nxagentCongestion);
+ #endif
+
+ if (nxagentOption(LinkType) != LINK_TYPE_NONE)
+ {
+ nxagentFlush = GetTimeInMillis();
+
+ time = nxagentFlush;
+
+ time = time - nxagentLastTime;
+
+ if (time < nxagentRateTime)
+ {
+ nxagentRate = ((nxagentRate * (nxagentRateTime - time) +
+ length) * 1000) / nxagentRateTime;
+ }
+ else
+ {
+ nxagentRate = (length * 1000) / nxagentRateTime;
+ }
+
+ nxagentLastTime = nxagentFlush;
+ }
+ }
+}
+
+static int nxagentDisplayErrorPredicate(Display *display, int error)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisplayErrorPredicate: CHECK! Error is [%d] with [%d][%d][%d][%d][%d].\n",
+ ((error == 1) || (dispatchException & DE_RESET) != 0 ||
+ (dispatchException & DE_TERMINATE) != 0 || nxagentException.sigHup > 0 ||
+ nxagentException.ioError > 0), error, (dispatchException & DE_RESET) != 0,
+ (dispatchException & DE_TERMINATE), nxagentException.sigHup > 0,
+ nxagentException.ioError > 0);
+ #endif
+
+ if (error == 0)
+ {
+ if ((dispatchException & DE_RESET) != 0 ||
+ (dispatchException & DE_TERMINATE))
+ {
+ return 1;
+ }
+ else if (nxagentException.sigHup > 0 ||
+ nxagentException.ioError > 0)
+ {
+ NXForceDisplayError(display);
+
+ return 1;
+ }
+ }
+
+ return error;
+}
+
+void nxagentInstallDisplayHandlers()
+{
+ /*
+ * If the display was already opened, be sure
+ * all structures are freed.
+ */
+
+ nxagentResetDisplayHandlers();
+
+ /*
+ * We want the Xlib I/O error handler to return,
+ * instead of quitting the application. Using
+ * setjmp()/longjmp() leaves the door open to
+ * unexpected bugs when dealing with interaction
+ * with the other X server layers.
+ */
+
+ NXHandleDisplayError(1);
+
+ NXSetDisplayBlockHandler(nxagentDisplayBlockHandler);
+
+ NXSetDisplayWriteHandler(nxagentDisplayWriteHandler);
+
+ NXSetDisplayFlushHandler(nxagentDisplayFlushHandler, NULL);
+
+ /*
+ * Override the default Xlib error handler.
+ */
+
+ XSetIOErrorHandler(nxagentIOErrorHandler);
+
+ /*
+ * Let Xlib become aware of our interrupts. In theory
+ * we don't need to have the error handler installed
+ * during the normal operations and could simply let
+ * the dispatcher handle the interrupts. In practice
+ * it's better to have Xlib invalidating the display
+ * as soon as possible rather than incurring in the
+ * risk of entering a loop that doesn't care checking
+ * the display errors explicitly.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInstallDisplayHandlers: Installing the error function predicate.\n");
+ #endif
+
+ NXSetDisplayErrorPredicate(nxagentDisplayErrorPredicate);
+}
+
+void nxagentPostInstallDisplayHandlers()
+{
+ /*
+ * This is executed after having opened the
+ * display, once we know the display address.
+ */
+
+ if (nxagentDisplay != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPostInstallDisplayHandlers: Initializing the NX display internals.\n");
+ #endif
+
+ NXInitDisplay(nxagentDisplay);
+/*
+FIXME: What is the most appropriate number of elements?
+
+ NXInitCache(nxagentDisplay, 128);
+*/
+ NXInitCache(nxagentDisplay, 256);
+
+ NXSetDisplayFlushHandler(nxagentDisplayFlushHandler, nxagentDisplay);
+ }
+
+ /*
+ * Handler for the Xlib protocol errors.
+ */
+
+ XSetErrorHandler(nxagentErrorHandler);
+}
+
+void nxagentResetDisplayHandlers()
+{
+ if (nxagentDisplay != NULL)
+ {
+ /*
+ * Free the internal nxcompext
+ * structures.
+ */
+
+ NXResetDisplay(nxagentDisplay);
+
+ /*
+ * Remove the display descriptor
+ * from the listened sockets.
+ */
+
+ nxagentRemoveXConnection();
+
+ /*
+ * Restart the suspended clients.
+ */
+
+ nxagentWakeupByReconnect();
+
+ nxagentReleaseAllSplits();
+ }
+
+ /*
+ * Reset the display to a healty state.
+ */
+
+ nxagentBuffer = 0;
+ nxagentBlocking = 0;
+ nxagentCongestion = 0;
+
+ /*
+ * Reset the counter of synchronization
+ * requests pending.
+ */
+
+ nxagentTokens.soft = 0;
+ nxagentTokens.hard = 0;
+ nxagentTokens.pending = 0;
+
+ /*
+ * Reset the current dispatch information.
+ */
+
+ nxagentDispatch.client = UNDEFINED;
+ nxagentDispatch.in = 0;
+ nxagentDispatch.out = 0;
+ nxagentDispatch.start = 0;
+}
+
+void nxagentInstallSignalHandlers()
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentInstallSignalHandlers: Installing the agent signal handlers.\n");
+ #endif
+
+ /*
+ * Keep the default X server's handlers for
+ * SIGINT and SIGTERM and restore the other
+ * signals of interest to our defaults.
+ */
+
+ struct sigaction newAction;
+
+ int result;
+
+ /*
+ * By default nxcomp installs its signal handlers.
+ * We need to ensure that SIGUSR1 and SIGUSR2 are
+ * ignored if the NX transport is not running.
+ */
+
+ newAction.sa_handler = nxagentSigusrHandler;
+
+ sigfillset(&newAction.sa_mask);
+
+ newAction.sa_flags = 0;
+
+ while (((result = sigaction(SIGUSR1, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for user signal 1.");
+ }
+
+ while (((result = sigaction(SIGUSR2, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for user signal 2.");
+ }
+
+ /*
+ * Reset the SIGALRM to the default.
+ */
+
+ nxagentStopTimer();
+
+ newAction.sa_handler = SIG_DFL;
+
+ sigfillset(&newAction.sa_mask);
+
+ while (((result = sigaction(SIGALRM, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for alarm signal.");
+ }
+
+ /*
+ * Let the smart schedule set the SIGALRM
+ * handler again.
+ */
+
+ nxagentInitTimer();
+
+ /*
+ * Install our own handler for the SIGHUP.
+ */
+
+ newAction.sa_handler = nxagentSighupHandler;
+
+ sigfillset(&newAction.sa_mask);
+
+ newAction.sa_flags = 0;
+
+ while (((result = sigaction(SIGHUP, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for session suspend.");
+ }
+
+ /*
+ * We need to be notified about our children.
+ */
+
+ newAction.sa_handler = nxagentSigchldHandler;
+
+ sigfillset(&newAction.sa_mask);
+
+ newAction.sa_flags = 0;
+
+ while (((result = sigaction(SIGCHLD, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for children.");
+ }
+}
+
+void nxagentPostInstallSignalHandlers()
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentPostInstallSignalHandlers: Dealing with the proxy signal handlers.\n");
+ #endif
+
+ /*
+ * Reconfigure our signal handlers to work well
+ * with the NX transport.
+ *
+ * Let our handlers manage the SIGINT and SIGTERM.
+ * The following calls will tell the NX transport
+ * to restore the old handlers (those originally
+ * installed by us or the X server).
+ */
+
+ NXTransSignal(SIGINT, NX_SIGNAL_DISABLE);
+ NXTransSignal(SIGTERM, NX_SIGNAL_DISABLE);
+
+ /*
+ * Also tell the proxy to ignore the SIGHUP.
+ */
+
+ NXTransSignal(SIGHUP, NX_SIGNAL_DISABLE);
+
+ /*
+ * Both the proxy and the agent need to catch
+ * their children, so we'll have to send the
+ * signal to transport.
+ */
+
+ NXTransSignal(SIGCHLD, NX_SIGNAL_DISABLE);
+
+ /*
+ * Let the NX transport take care of SIGUSR1
+ * and SIGUSR2.
+ */
+}
+
+void nxagentResetSignalHandlers()
+{
+ struct sigaction newAction;
+
+ int result;
+
+ memset(&newAction, 0, sizeof(newAction));
+
+ /*
+ * Reset the signal handlers
+ * to a well known state.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetSignalHandlers: Resetting the agent the signal handlers.\n");
+ #endif
+
+ /*
+ * Reset the SIGALRM to the default.
+ */
+
+ nxagentStopTimer();
+
+ newAction.sa_handler = SIG_DFL;
+
+ sigfillset(&newAction.sa_mask);
+
+ while (((result = sigaction(SIGALRM, &newAction,
+ NULL)) == -1) && (errno == EINTR));
+
+ if (result == -1)
+ {
+ FatalError("Can't set the handler for alarm signal.");
+ }
+
+ /*
+ * Let the smart schedule set the SIGALRM
+ * handler again.
+ */
+
+ nxagentInitTimer();
+
+}
+
+void nxagentOpenDisplay(int argc, char *argv[])
+{
+ int i;
+
+ if (!nxagentDoFullGeneration) return;
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ startTime = GetTimeInMillis();
+
+ fprintf(stderr, "Display: Opening the display on real X server with time [%d] ms.\n",
+ GetTimeInMillis() - startTime);
+
+ #endif
+
+ /*
+ * Initialize the reconnector only in the case
+ * of persistent sessions.
+ */
+
+ if (nxagentOption(Persistent))
+ {
+ nxagentInitReconnector();
+ }
+
+ if (*nxagentDisplayName == '\0')
+ {
+ strncpy(nxagentDisplayName, XDisplayName(NULL), 1023);
+
+ nxagentDisplayName[1023] = '\0';
+ }
+
+ nxagentCloseDisplay();
+
+ nxagentInstallSignalHandlers();
+
+ nxagentInstallDisplayHandlers();
+
+ nxagentDisplay = nxagentInternalOpenDisplay(nxagentDisplayName);
+
+ nxagentPostInstallSignalHandlers();
+
+ nxagentPostInstallDisplayHandlers();
+
+ if (nxagentDisplay == NULL)
+ {
+/*
+FIXME: The agent should never exit the program with a FatalError()
+ but rather use a specific function that may eventually call
+ FatalError() on its turn.
+*/
+ FatalError("Unable to open display '%s'.\n", nxagentDisplayName);
+ }
+
+ if (nxagentSynchronize)
+ XSynchronize(nxagentDisplay, True);
+
+ nxagentXConnectionNumber = XConnectionNumber(nxagentDisplay);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenDisplay: Display image order is [%d] bitmap order is [%d].\n",
+ ImageByteOrder(nxagentDisplay), BitmapBitOrder(nxagentDisplay));
+
+ fprintf(stderr, "nxagentOpenDisplay: Display scanline unit is [%d] scanline pad is [%d].\n",
+ BitmapUnit(nxagentDisplay), BitmapPad(nxagentDisplay));
+ #endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 1.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#1 U 1 1 256 bits (0 KB) -> 150 bits (0 KB) -> 256/1 -> 150/1 = 1.707:1
+#20 1 1 119104 bits (15 KB) -> 28 bits (0 KB) -> 119104/1 -> 28/1 = 4253.714:1
+#98 2 512 bits (0 KB) -> 84 bits (0 KB) -> 256/1 -> 42/1 = 6.095:1
+*/
+
+ sleep(60);
+
+ #endif
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ fprintf(stderr, "Display: Display on real X server opened with time [%d] ms.\n",
+ GetTimeInMillis() - startTime);
+
+ #endif
+
+ nxagentUseNXTrans =
+ nxagentPostProcessArgs(nxagentDisplayName, nxagentDisplay,
+ DefaultScreenOfDisplay(nxagentDisplay));
+
+ /*
+ * Processing the arguments all the timeouts
+ * have been set. Now we have to change the
+ * screen-saver timeout.
+ */
+
+ nxagentSetScreenSaverTime();
+
+ nxagentInitVisuals();
+
+ nxagentNumDefaultColormaps = nxagentNumVisuals;
+ nxagentDefaultColormaps = (Colormap *)malloc(nxagentNumDefaultColormaps *
+ sizeof(Colormap));
+
+ for (i = 0; i < nxagentNumDefaultColormaps; i++)
+ {
+ nxagentDefaultColormaps[i] = XCreateColormap(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ nxagentVisuals[i].visual,
+ AllocNone);
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 4.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ nxagentBlackPixel = BlackPixel(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ nxagentWhitePixel = WhitePixel(nxagentDisplay, DefaultScreen(nxagentDisplay));
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ /*
+ * Initialize the agent's event mask that will be requested
+ * for the root and all the top level windows. If the nested
+ * window is a child of an existing window, we will need to
+ * receive StructureNotify events. If we are going to manage
+ * the changes in root window's visibility we'll also need
+ * VisibilityChange events.
+ */
+
+/*
+FIXME: Use of nxagentParentWindow is strongly deprecated.
+ We need also to clarify which events are selected
+ in the diferent operating modes.
+*/
+
+ nxagentInitDefaultEventMask();
+
+ /*
+ * Initialize the pixmap depths and formats.
+ */
+
+ nxagentInitDepths();
+
+ nxagentInitPixmapFormats();
+ (void) nxagentCheckForPixmapFormatsCompatibility();
+
+ /*
+ * Create a pixmap for each depth matching the
+ * local supported formats with format available
+ * on the remote display.
+ */
+
+ nxagentSetDefaultDrawables();
+
+ #ifdef RENDER
+ if (nxagentRenderEnable)
+ {
+ nxagentRenderExtensionInit();
+ }
+ #endif
+
+ /*
+ * This GC is referenced in Cursor.c. It can be
+ * probably removed.
+ */
+
+ nxagentBitmapGC = XCreateGC(nxagentDisplay, nxagentDefaultDrawables[1], 0L, NULL);
+
+ /*
+ * Note that this "confine window" is useless at the
+ * moment as we reimplement nxagentConstrainCursor()
+ * to skip the "constrain" stuff.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenDisplay: Going to create agent's confine window.\n");
+ #endif
+
+ nxagentConfineWindow = XCreateWindow(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ 0, 0, 1, 1, 0, 0,
+ InputOnly,
+ CopyFromParent,
+ 0L, NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenDisplay: Created agent's confine window with id [%ld].\n",
+ nxagentConfineWindow);
+ #endif
+
+ if (!(nxagentUserGeometry.flag & XValue))
+ {
+ nxagentChangeOption(RootX, 0);
+ }
+
+ if (!(nxagentUserGeometry.flag & YValue))
+ {
+ nxagentChangeOption(RootY, 0);
+ }
+
+ if (nxagentParentWindow == 0)
+ {
+ if (!(nxagentUserGeometry.flag & WidthValue))
+ {
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(RootWidth, DisplayWidth(nxagentDisplay, DefaultScreen(nxagentDisplay)));
+ }
+ else
+ {
+ nxagentChangeOption(RootWidth, 3 * DisplayWidth(nxagentDisplay,
+ DefaultScreen(nxagentDisplay)) / 4);
+ }
+ }
+
+ if (!(nxagentUserGeometry.flag & HeightValue))
+ {
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(RootHeight, DisplayHeight(nxagentDisplay, DefaultScreen(nxagentDisplay)));
+ }
+ else
+ {
+ nxagentChangeOption(RootHeight, 3 * DisplayHeight(nxagentDisplay,
+ DefaultScreen(nxagentDisplay)) / 4);
+ }
+ }
+ }
+
+ if (!nxagentUserBorderWidth)
+ {
+ nxagentChangeOption(BorderWidth, 1);
+ }
+
+ nxagentLogoDepth = DefaultDepth(nxagentDisplay,
+ DefaultScreen(nxagentDisplay)
+ );
+
+ nxagentLogoBlack = 0x000000;
+ nxagentLogoRed = 0xff0000;
+ nxagentLogoWhite = 0xffffff;
+ nxagentLogoGray = 0x222222;
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.1.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ useXpmIcon = nxagentMakeIcon(nxagentDisplay, &nxagentIconPixmap, &nxagentIconShape);
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 5.2.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#84 2 512 bits (0 KB) -> 76 bits (0 KB) -> 256/1 -> 38/1 = 6.737:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenDisplay: Watchpoint 6.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ fprintf(stderr, "Display: Open of the display finished with time [%d] ms.\n",
+ GetTimeInMillis() - startTime);
+
+ #endif
+
+ if (nxagentOption(Persistent))
+ {
+ reconnectDisplayState = EVERYTHING_DONE;
+ }
+}
+
+void nxagentSetDefaultVisual(void)
+{
+ XVisualInfo vi;
+
+ int i;
+
+ if (nxagentUserDefaultClass || nxagentUserDefaultDepth)
+ {
+ nxagentDefaultVisualIndex = UNDEFINED;
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ if ((!nxagentUserDefaultClass ||
+ nxagentVisuals[i].class == nxagentDefaultClass)
+ &&
+ (!nxagentUserDefaultDepth ||
+ nxagentVisuals[i].depth == nxagentDefaultDepth))
+ {
+ nxagentDefaultVisualIndex = i;
+
+ break;
+ }
+ }
+
+ if (nxagentDefaultVisualIndex == UNDEFINED)
+ {
+ FatalError("Unable to find desired default visual.\n");
+ }
+ }
+ else
+ {
+ vi.visualid = XVisualIDFromVisual(DefaultVisual(nxagentDisplay,
+ DefaultScreen(nxagentDisplay)));
+ nxagentDefaultVisualIndex = 0;
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ if (vi.visualid == nxagentVisuals[i].visualid)
+ {
+ nxagentDefaultVisualIndex = i;
+ }
+ }
+ }
+}
+
+void nxagentInitVisuals(void)
+{
+ XVisualInfo vi;
+ XVisualInfo *viList = NULL;
+
+ long mask;
+ int i, viNumList;
+
+ mask = VisualScreenMask;
+ vi.screen = DefaultScreen(nxagentDisplay);
+ vi.depth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ viList = XGetVisualInfo(nxagentDisplay, mask, &vi, &viNumList);
+ nxagentVisuals = (XVisualInfo *) malloc(viNumList * sizeof(XVisualInfo));
+ nxagentNumVisuals = 0;
+
+ for (i = 0; i < viNumList; i++)
+ {
+ if (viList[i].depth == vi.depth)
+ {
+ if (nxagentVisuals != NULL)
+ {
+ memcpy(nxagentVisuals + nxagentNumVisuals, viList + i, sizeof(XVisualInfo));
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitVisuals: Visual:\n");
+ fprintf(stderr, "\tdepth = %d\n", nxagentVisuals[nxagentNumVisuals].depth);
+ fprintf(stderr, "\tclass = %d\n", nxagentVisuals[nxagentNumVisuals].class);
+ fprintf(stderr, "\tmask = (%lu,%lu,%lu)\n",
+ nxagentVisuals[nxagentNumVisuals].red_mask,
+ nxagentVisuals[nxagentNumVisuals].green_mask,
+ nxagentVisuals[nxagentNumVisuals].blue_mask);
+ fprintf(stderr, "\tcolormap size = %d\n", nxagentVisuals[nxagentNumVisuals].colormap_size);
+ fprintf(stderr, "\tbits_per_rgb = %d\n", nxagentVisuals[nxagentNumVisuals].bits_per_rgb);
+ #endif
+
+ nxagentNumVisuals++;
+ }
+ }
+
+ if (nxagentVisuals != NULL)
+ {
+ nxagentVisuals = (XVisualInfo *) realloc(nxagentVisuals,
+ nxagentNumVisuals * sizeof(XVisualInfo));
+ }
+
+ XFree(viList);
+
+ if (nxagentNumVisuals == 0 || nxagentVisuals == NULL)
+ {
+ FatalError("Unable to find any visuals.\n");
+ }
+
+ nxagentSetDefaultVisual();
+}
+
+void nxagentInitDepths()
+{
+ #ifdef TEST
+ int i;
+ #endif
+
+ nxagentDepths = XListDepths(nxagentDisplay, DefaultScreen(nxagentDisplay),
+ &nxagentNumDepths);
+
+ if (nxagentDepths == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentInitDepths: PANIC! Failed to get available depths.\n");
+ #endif
+
+ FatalError("Failed to get available depths and pixmap formats.");
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentInitDepths: Got [%d] available depths:\n",
+ nxagentNumDepths);
+
+ for (i = 0; i < nxagentNumDepths; i++)
+ {
+ fprintf(stderr, " [%d]", nxagentDepths[i]);
+ }
+
+ fprintf(stderr, ".\n");
+ }
+ #endif
+}
+
+void nxagentInitPixmapFormats()
+{
+ int i, j;
+ int depth;
+
+ /*
+ * Formats are created with no care of which are supported
+ * on the real display. Creating only formats supported
+ * by the remote end makes troublesome handling migration
+ * of session from a display to another.
+ */
+
+ nxagentNumPixmapFormats = 0;
+
+/*
+XXX: Some X server doesn't list 1 among available depths...
+*/
+
+ nxagentPixmapFormats = malloc((nxagentNumDepths + 1) * sizeof(XPixmapFormatValues));
+
+ for (i = 1; i <= MAXDEPTH; i++)
+ {
+ depth = 0;
+
+ if (i == 1)
+ {
+ depth = 1;
+ }
+ else
+ {
+ for (j = 0; j < nxagentNumDepths; j++)
+ {
+ if (nxagentDepths[j] == i)
+ {
+ depth = i;
+
+ break;
+ }
+ }
+ }
+
+ if (depth != 0)
+ {
+ if (nxagentNumPixmapFormats >= MAXFORMATS)
+ {
+ FatalError("nxagentInitPixmapFormats: MAXFORMATS is too small for this server.\n");
+ }
+
+ nxagentPixmapFormats[nxagentNumPixmapFormats].depth = depth;
+ nxagentPixmapFormats[nxagentNumPixmapFormats].bits_per_pixel = nxagentBitsPerPixel(depth);
+ nxagentPixmapFormats[nxagentNumPixmapFormats].scanline_pad = BITMAP_SCANLINE_PAD;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitPixmapFormats: Set format [%d] to depth [%d] "
+ "bits per pixel [%d] scanline pad [%d].\n", nxagentNumPixmapFormats,
+ depth, nxagentPixmapFormats[nxagentNumPixmapFormats].bits_per_pixel,
+ BITMAP_SCANLINE_PAD);
+ #endif
+
+ nxagentNumPixmapFormats++;
+ }
+ }
+
+ nxagentRemotePixmapFormats = XListPixmapFormats(nxagentDisplay, &nxagentRemoteNumPixmapFormats);
+
+ if (nxagentRemotePixmapFormats == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitPixmapFormats: WARNING! Failed to get available remote pixmap formats.\n");
+ #endif
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentInitPixmapFormats: Got [%d] available remote pixmap formats:\n",
+ nxagentRemoteNumPixmapFormats);
+
+ for (i = 0; i < nxagentRemoteNumPixmapFormats; i++)
+ {
+ fprintf(stderr, "nxagentInitPixmapFormats: Remote pixmap format [%d]: depth [%d] "
+ "bits_per_pixel [%d] scanline_pad [%d].\n", i, nxagentRemotePixmapFormats[i].depth,
+ nxagentRemotePixmapFormats[i].bits_per_pixel, nxagentRemotePixmapFormats[i].scanline_pad);
+ }
+ }
+ #endif
+}
+
+void nxagentSetDefaultDrawables()
+{
+ int i, j;
+
+ for (i = 0; i <= MAXDEPTH; i++)
+ {
+ nxagentDefaultDrawables[i] = None;
+ }
+
+ for (i = 0; i < nxagentNumPixmapFormats; i++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: Checking remote pixmap format [%d] with depth [%d] "
+ "bits per pixel [%d] scanline pad [%d].\n", i, nxagentPixmapFormats[i].depth,
+ nxagentPixmapFormats[i].bits_per_pixel, nxagentPixmapFormats[i].scanline_pad);
+ #endif
+
+ if (nxagentPixmapFormats[i].depth == 24)
+ {
+ if (nxagentPixmapFormats[i].bits_per_pixel == 24)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: WARNING! Assuming remote pixmap "
+ "format [%d] as true 24 bits.\n", i);
+ #endif
+
+ nxagentTrue24 = True;
+ }
+ }
+
+ for (j = 0; j < nxagentNumDepths; j++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: Checking depth at index [%d] with pixmap depth [%d] "
+ "and display depth [%d].\n", j, nxagentPixmapFormats[i].depth, nxagentDepths[j]);
+ #endif
+
+ if ((nxagentPixmapFormats[i].depth == 1 ||
+ nxagentPixmapFormats[i].depth == nxagentDepths[j]) &&
+ nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] == None)
+ {
+ nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] =
+ XCreatePixmap(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ 1, 1, nxagentPixmapFormats[i].depth);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: Created default drawable [%lu] for depth [%d].\n",
+ nxagentDefaultDrawables[nxagentPixmapFormats[i].depth], nxagentPixmapFormats[i].depth);
+ #endif
+ }
+ }
+
+ if (nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] == None)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: WARNING! Forcing default drawable for depth [%d].\n",
+ nxagentPixmapFormats[i].depth);
+ #endif
+
+ nxagentDefaultDrawables[nxagentPixmapFormats[i].depth] =
+ XCreatePixmap(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ 1, 1, nxagentPixmapFormats[i].depth);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetDefaultDrawables: Created default drawable [%lu] for depth [%d].\n",
+ nxagentDefaultDrawables[nxagentPixmapFormats[i].depth], nxagentPixmapFormats[i].depth);
+ #endif
+ }
+ }
+}
+
+void nxagentCloseDisplay()
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentCloseDisplay: Called with full generation [%d] and display [%p].\n",
+ nxagentDoFullGeneration, (void *) nxagentDisplay);
+ #endif
+
+ if (nxagentDoFullGeneration == 0 ||
+ nxagentDisplay == NULL)
+ {
+ return;
+ }
+
+ /*
+ * If nxagentDoFullGeneration is true, all
+ * the X resources will be destroyed upon
+ * closing the display connection, so there
+ * is no real need to generate additional
+ * traffic
+ */
+
+ free(nxagentDefaultColormaps);
+ nxagentDefaultColormaps = NULL;
+
+ XFree(nxagentVisuals);
+ nxagentVisuals = NULL;
+
+ free(nxagentDepths);
+ nxagentDepths = NULL;
+
+ XFree(nxagentPixmapFormats);
+ nxagentPixmapFormats = NULL;
+
+ XFree(nxagentRemotePixmapFormats);
+ nxagentRemotePixmapFormats = NULL;
+
+ nxagentFreeFontCache();
+/*
+FIXME: Is this needed?
+
+ nxagentFreeFontMatchStuff();
+*/
+
+ /*
+ * Free the image cache. This is useful
+ * for detecting memory leaks.
+ */
+
+ if (nxagentDisplay != NULL)
+ {
+ NXFreeCache(nxagentDisplay);
+
+ NXResetDisplay(nxagentDisplay);
+ }
+
+ /*
+ * Kill all the running dialogs.
+ */
+
+ nxagentTerminateDialogs();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCloseDisplay: Setting the display to NULL.\n");
+ #endif
+
+ XCloseDisplay(nxagentDisplay);
+
+ nxagentDisplay = NULL;
+}
+
+static FILE *nxagentLookForIconFile(char *iconName, const char *permission,
+ char *return_path)
+{
+ char *path;
+ char *end;
+ char singlePath[PATH_MAX];
+ int breakLoop;
+ FILE *fptr = NULL;
+
+ #ifdef WIN32
+ const char separator = ';';
+ const char *slash = "\\";
+ #else
+ const char separator = ':';
+ const char *slash = "/";
+ #endif
+
+ if ((path = getenv("PATH")) == NULL)
+ {
+ return NULL;
+ }
+
+ for(breakLoop = 0; breakLoop == 0 && fptr == NULL; )
+ {
+ end = strchr(path, separator);
+
+ if (end != NULL)
+ {
+ strncpy(singlePath, path, (unsigned long)(end - path));
+
+ singlePath[(unsigned long)(end - path)] = 0;
+
+ path = end + 1;
+ }
+ else
+ {
+ strcpy(singlePath, path);
+
+ breakLoop = 1;
+ }
+
+ if (singlePath[strlen(singlePath)- 1] == slash[0])
+ {
+ singlePath[strlen(singlePath)- 1] = 0;
+ }
+
+ if (strlen(singlePath) + strlen(iconName) + 1 < PATH_MAX)
+ {
+ strncat(singlePath, slash, 1);
+ strcat(singlePath, iconName);
+
+ if ((fptr = fopen(singlePath, permission)) != NULL)
+ {
+ strcpy(return_path, singlePath);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Error: Path too long.\n");
+ }
+ }
+
+ return fptr;
+}
+
+Bool nxagentMakeIcon(Display *display, Pixmap *nxIcon, Pixmap *nxMask)
+{
+ char default_path [PATH_MAX];
+ char icon_path [PATH_MAX];
+ FILE *icon_fp;
+ int status;
+ Bool success = False;
+ XlibPixmap IconPixmap;
+ XlibPixmap IconShape;
+ char* agent_icon_name;
+ char** agentIconData;
+
+ /*
+ * selecting x2go icon when running as X2Go agent
+ */
+ if(nxagentX2go)
+ {
+ agent_icon_name=X2GOAGENT_ICON_NAME;
+ agentIconData=x2goagentIconData;
+ }
+ else
+ {
+ agent_icon_name=NXAGENT_ICON_NAME;
+ agentIconData=nxagentIconData;
+ }
+
+
+ snprintf(default_path, PATH_MAX-1, "/usr/NX/share/images/%s", agent_icon_name);
+
+ if ((icon_fp = fopen(default_path, "r")) == NULL)
+ {
+ icon_fp = nxagentLookForIconFile(agent_icon_name, "r", icon_path);
+
+ if (icon_fp != NULL)
+ {
+ fclose (icon_fp);
+ success = True;
+ }
+ }
+ else
+ {
+ fclose (icon_fp);
+ success = True;
+ strcpy(icon_path, default_path);
+ }
+
+ if (success)
+ {
+ status = XpmReadFileToPixmap(display,
+ DefaultRootWindow(display),
+ icon_path,
+ &IconPixmap,
+ &IconShape,
+ NULL);
+
+ if (status != XpmSuccess)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMakeIcon: Xpm operation failed with error '%s'.\n",
+ XpmGetErrorString(status));
+ #endif
+
+ success = False;
+ }
+ }
+
+ if (!success)
+ {
+ status = XpmCreatePixmapFromData(display,
+ DefaultRootWindow(display),
+ agentIconData,
+ &IconPixmap,
+ &IconShape,
+ NULL);
+
+ if (status != XpmSuccess)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMakeIcon: Xpm operation failed with error '%s'.\n",
+ XpmGetErrorString(status));
+ #endif
+
+ success = False;
+ }
+ else
+ {
+ success = True;
+ }
+ }
+
+
+ *nxIcon = IconPixmap;
+ *nxMask = IconShape;
+
+ return success;
+}
+
+Bool nxagentXServerGeometryChanged()
+{
+ return (WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) !=
+ WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplayBackup))) ||
+ (HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) !=
+ HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplayBackup)));
+}
+
+void nxagentBackupDisplayInfo(void)
+{
+ if (nxagentDisplayInfoSaved)
+ {
+ return;
+ }
+
+ /*
+ * Since we need the display structure
+ * in order to behave correctly when no X
+ * connection is available, we must always
+ * have a good display record.
+ * It can be discarded only when a new X
+ * connection is available, so we store it
+ * in order to destroy whenever the recon-
+ * nection succed.
+ */
+
+ nxagentDisplayBackup = nxagentDisplay;
+ nxagentBitmapGCBackup = nxagentBitmapGC;
+ nxagentDepthsRecBackup = nxagentDepths;
+ nxagentNumDepthsRecBackup = nxagentNumDepths;
+ nxagentNumDefaultColormapsRecBackup = nxagentNumDefaultColormaps;
+ nxagentVisualsRecBackup = nxagentVisuals;
+ nxagentNumVisualsRecBackup = nxagentNumVisuals;
+ if (nxagentVisualHasBeenIgnored)
+ {
+ free(nxagentVisualHasBeenIgnored);
+ nxagentVisualHasBeenIgnored = NULL;
+ }
+ nxagentVisualHasBeenIgnored = malloc(nxagentNumVisuals * sizeof(Bool));
+ nxagentDefaultDepthRecBackup = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ nxagentDisplayWidthRecBackup = DisplayWidth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ nxagentDisplayHeightRecBackup = DisplayHeight(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ nxagentRenderEnableRecBackup = nxagentRenderEnable;
+
+ nxagentDisplayInfoSaved = True;
+}
+
+void nxagentCleanupBackupDisplayInfo(void)
+{
+ free(nxagentDepthsRecBackup);
+ nxagentNumDepthsRecBackup = 0;
+
+ nxagentNumDefaultColormapsRecBackup = 0;
+
+ free(nxagentVisualsRecBackup);
+ nxagentNumVisualsRecBackup = 0;
+
+ if (nxagentVisualHasBeenIgnored)
+ {
+ free(nxagentVisualHasBeenIgnored);
+ nxagentVisualHasBeenIgnored = NULL;
+ }
+
+ nxagentDefaultDepthRecBackup = 0;
+ nxagentDisplayWidthRecBackup = 0;
+ nxagentDisplayHeightRecBackup = 0;
+
+ if (nxagentDisplayBackup)
+ {
+ XCloseDisplay(nxagentDisplayBackup);
+
+ nxagentDisplayBackup = NULL;
+ }
+
+ if (nxagentBitmapGCBackup)
+ {
+ if (nxagentDisplayBackup)
+ {
+ XFreeGC(nxagentDisplayBackup, nxagentBitmapGCBackup);
+ }
+ else
+ {
+ free(nxagentBitmapGCBackup);
+ }
+
+ nxagentBitmapGCBackup = NULL;
+ }
+
+ nxagentDisplayInfoSaved = False;
+}
+
+void nxagentDisconnectDisplay(void)
+{
+ switch (reconnectDisplayState)
+ {
+ case EVERYTHING_DONE:
+ if (nxagentBitmapGC &&
+ nxagentBitmapGCBackup &&
+ (nxagentBitmapGC != nxagentBitmapGCBackup))
+ {
+ XFreeGC(nxagentDisplay, nxagentBitmapGC);
+ }
+
+ nxagentBitmapGC = nxagentBitmapGCBackup;
+ case GOT_PIXMAP_FORMAT_LIST:
+ case GOT_DEPTH_LIST:
+ case ALLOC_DEF_COLORMAP:
+ if (nxagentDefaultColormaps)
+ {
+ int i;
+
+ for (i = 0; i < nxagentNumDefaultColormaps; i++)
+ {
+ nxagentDefaultColormaps[i] = None;
+ }
+ }
+ case GOT_VISUAL_INFO:
+ case OPENED:
+ /*
+ * Actually we need the nxagentDisplay
+ * structure in order to let the agent
+ * go when no X connection is available.
+ */
+
+ if (nxagentDisplay &&
+ nxagentDisplayBackup &&
+ (nxagentDisplay != nxagentDisplayBackup))
+ {
+ XCloseDisplay(nxagentDisplay);
+ }
+ case NOTHING:
+ nxagentDisplay = nxagentDisplayBackup;
+ break;
+ default:
+ FatalError("Display is in unknown state. Can't continue.");
+ }
+
+ reconnectDisplayState = NOTHING;
+}
+
+static int nxagentCheckForDefaultDepthCompatibility()
+{
+ /*
+ * Depending on the (reconnect) tolerance checks value, this
+ * function checks stricter or looser:
+ * - Strict means that the old and new default depth values
+ * must match exactly.
+ * - Safe or Risky means that the default depth values might differ,
+ * but the new default depth value must be at least as
+ * high as the former default depth value. This is
+ * recommended, because it allows clients with a
+ * higher default depth value to still connect, but
+ * not lose functionality.
+ * - Bypass means that all of these checks are essentially
+ * deactivated. This is probably a very bad idea.
+ */
+
+ int dDepth;
+
+ dDepth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+
+ const unsigned int tolerance = nxagentOption(ReconnectTolerance);
+
+ if (ToleranceChecksBypass <= tolerance)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: WARNING! Not proceeding with any checks, "
+ "because tolerance [%u] higher than or equal [%u]. New default depth value "
+ "is [%d], former default depth value is [%d].\n", tolerance,
+ ToleranceChecksBypass, dDepth, nxagentDefaultDepthRecBackup);
+ #endif
+
+ return 1;
+ }
+
+ if (nxagentDefaultDepthRecBackup == dDepth)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: New default depth [%d] "
+ "matches with old default depth.\n", dDepth);
+ #endif
+
+ return 1;
+ }
+ else if ((ToleranceChecksSafe <= tolerance) && (nxagentDefaultDepthRecBackup < dDepth))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: WARNING! New default depth [%d] "
+ "higher than the old default depth [%d] at tolerance [%u].\n", dDepth,
+ nxagentDefaultDepthRecBackup, tolerance);
+ #endif
+
+ return 1;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDefaultDepthCompatibility: WARNING! New default depth [%d] "
+ "doesn't match with old default depth [%d] at tolerance [%u].\n", dDepth,
+ nxagentDefaultDepthRecBackup, tolerance);
+ #endif
+
+ return 0;
+ }
+}
+
+static int nxagentCheckForDepthsCompatibility()
+{
+ /*
+ * Depending on the (reconnect) tolerance checks value, this
+ * function checks stricter or looser:
+ * - Strict means that the number of old and new depths must
+ * match exactly and every old depth value must be
+ * available in the new depth array.
+ * - Safe means that the number of depths might diverge,
+ * but all former depth must also be included in the
+ * new depth array. This is recommended, because
+ * it allows clients with more depths to still
+ * connect, but not lose functionality.
+ * - Risky means that the new depths array is allowed to be
+ * smaller than the old depths array, but at least
+ * one depth value must be included in both.
+ * This is potentially unsafe.
+ * - Bypass or higher means that all of these checks are
+ * essentially deactivated. This is a very bad idea.
+ */
+
+ const unsigned int tolerance = nxagentOption(ReconnectTolerance);
+
+ if (ToleranceChecksBypass <= tolerance)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! Not proceeding with any checks, "
+ "because tolerance [%u] higher than or equal [%u]. Number of newly available depths "
+ "is [%d], number of old depths is [%d].\n", tolerance, ToleranceChecksBypass,
+ nxagentNumDepths, nxagentNumDepthsRecBackup);
+ #endif
+
+ return 1;
+ }
+
+ if ((ToleranceChecksStrict == tolerance) && (nxagentNumDepths != nxagentNumDepthsRecBackup))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! No tolerance allowed and "
+ "number of new available depths [%d] doesn't match with number of old "
+ "depths [%d].\n", nxagentNumDepths,
+ nxagentNumDepthsRecBackup);
+ #endif
+
+ return 0;
+ }
+
+ if ((ToleranceChecksSafe == tolerance) && (nxagentNumDepths < nxagentNumDepthsRecBackup))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! Tolerance [%u] not "
+ "high enough and number of new available depths [%d] "
+ "lower than number of old depths [%d].\n", tolerance,
+ nxagentNumDepths, nxagentNumDepthsRecBackup);
+ #endif
+
+ return 0;
+ }
+
+ /*
+ * By now the tolerance is either:
+ * - Strict and both depth numbers match
+ * - Safe and:
+ * o the number of old and new depths matches exactly, or
+ * o the number of old depths is lower than the number
+ * of new depths
+ * - Risky
+ */
+
+ bool compatible = true;
+ bool one_match = false;
+ bool matched = false;
+ int total_matches = 0;
+
+ /*
+ * FIXME: within this loop, we try to match all "new" depths
+ * against the "old" depths. Depending upon the flexibility
+ * value, either all "new" depths must have a corresponding
+ * counterpart in the "old" array, or at least one value
+ * must be included in both.
+ * Is this safe enough though?
+ * Shouldn't we better try to match entries in the "old"
+ * depths array against the "new" depths array, such that
+ * we know that all "old" values are covered by "new"
+ * values? Or is it more important that "new" values are
+ * covered by "old" ones, with potentially more "old"
+ * values lingering around that cannot be displayed by the
+ * connected client?
+ *
+ * This section probably needs a revisit at some point in time.
+ */
+ for (int i = 0; i < nxagentNumDepths; ++i)
+ {
+ matched = false;
+
+ for (int j = 0; j < nxagentNumDepthsRecBackup; ++j)
+ {
+ if (nxagentDepths[i] == nxagentDepthsRecBackup[j])
+ {
+ matched = true;
+ one_match = true;
+ ++total_matches;
+
+ break;
+ }
+ }
+
+ if ((ToleranceChecksRisky > tolerance) && (!matched))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! Tolerance [%u] too low and "
+ "failed to match available depth [%d].\n", tolerance, nxagentDepths[i]);
+ #endif
+
+ compatible = false;
+
+ break;
+ }
+ }
+
+ /*
+ * At Risky tolerance, only one match is necessary to be "compatible".
+ */
+ if (ToleranceChecksRisky == tolerance)
+ {
+ compatible = one_match;
+ }
+
+ int ret = (!(!compatible));
+
+ if (compatible)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: Internal depths match with "
+ "remote depths at tolerance [%u].\n", tolerance);
+ #endif
+
+ if (total_matches != nxagentNumDepths)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: only some [%d] of the new depths [%d] "
+ "match with old depths [%d] at tolerance [%u].\n", total_matches, nxagentNumDepths,
+ nxagentNumDepthsRecBackup, tolerance);
+ #endif
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForDepthsCompatibility: WARNING! New available depths [%d] don't match "
+ "with old depths [%d] at tolerance [%u]. Only [%d] depth values matched.\n",
+ nxagentNumDepths, nxagentNumDepthsRecBackup, tolerance, total_matches);
+ #endif
+ }
+
+ return (ret);
+}
+
+static int nxagentCheckForPixmapFormatsCompatibility()
+{
+ /*
+ * Depending on the (reconnect) tolerance checks value, this
+ * function checks stricter or looser:
+ * - Strict means that the number of internal and external
+ * pixmap formats must match exactly and every
+ * internal pixmap format must be available in the
+ * external pixmap format array.
+ * - Safe means that the number of pixmap formats might
+ * diverge, but all internal pixmap formats must
+ * also be included in the external pixmap formats
+ * array. This is recommended, because it allows
+ * clients with more pixmap formats to still connect,
+ * but not lose functionality.
+ * - Risky means that the internal pixmap formats array is
+ * allowed to be smaller than the external pixmap
+ * formats array, but at least one pixmap format must
+ * be included in both. This is potentially unsafe.
+ * - Bypass or higher means that all of these checks are
+ * essentially deactivated. This is a very bad idea.
+ */
+
+ const unsigned int tolerance = nxagentOption(ReconnectTolerance);
+
+ if (ToleranceChecksBypass <= tolerance)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Not proceeding with any checks, "
+ "because tolerance [%u] higher than or equal [%u]. Number of internally available "
+ "pixmap formats is [%d], number of externally available pixmap formats is [%d].\n",
+ tolerance, ToleranceChecksBypass, nxagentNumPixmapFormats, nxagentRemoteNumPixmapFormats);
+ #endif
+
+ return 1;
+ }
+
+ if ((ToleranceChecksStrict == tolerance) && (nxagentNumPixmapFormats != nxagentRemoteNumPixmapFormats))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! No tolerance allowed and number "
+ "of internal pixmap formats [%d] doesn't match with number of remote formats [%d].\n",
+ nxagentNumPixmapFormats, nxagentRemoteNumPixmapFormats);
+ #endif
+
+ return 0;
+ }
+
+ if ((ToleranceChecksSafe == tolerance) && (nxagentNumPixmapFormats > nxagentRemoteNumPixmapFormats))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Tolerance [%u] too low "
+ "and number of internal pixmap formats [%d] higher than number of external formats [%d].\n",
+ tolerance, nxagentNumPixmapFormats, nxagentRemoteNumPixmapFormats);
+ #endif
+
+ return 0;
+ }
+
+ /*
+ * By now the tolerance is either:
+ * - Strict
+ * - Safe and:
+ * o the number of internal and external pixmap formats
+ * matches exactly, or
+ * o the number of external pixmap formats is higher than
+ * the number of internal pixmap formats,
+ * - Risky
+ */
+
+ bool compatible = true;
+ bool matched = false;
+ int total_matches = 0;
+
+ for (int i = 0; i < nxagentNumPixmapFormats; ++i)
+ {
+ matched = false;
+
+ for (int j = 0; j < nxagentRemoteNumPixmapFormats; ++j)
+ {
+ if (nxagentPixmapFormats[i].depth == nxagentRemotePixmapFormats[j].depth &&
+ nxagentPixmapFormats[i].bits_per_pixel == nxagentRemotePixmapFormats[j].bits_per_pixel &&
+ nxagentPixmapFormats[i].scanline_pad == nxagentRemotePixmapFormats[j].scanline_pad)
+ {
+ matched = true;
+ ++total_matches;
+
+ break;
+ }
+ }
+
+ if ((ToleranceChecksRisky > tolerance) && (!matched))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Tolerance [%u] too low "
+ "and failed to match internal pixmap format (depth [%d] bpp [%d] pad [%d]).\n",
+ tolerance, nxagentPixmapFormats[i].depth, nxagentPixmapFormats[i].bits_per_pixel,
+ nxagentPixmapFormats[i].scanline_pad);
+ #endif
+
+ compatible = false;
+ }
+ }
+
+ int ret = !(!(compatible));
+
+ if (compatible)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: Internal pixmap formats match with "
+ "remote pixmap formats at tolerance [%u].\n", tolerance);
+ #endif
+
+ if (total_matches != nxagentNumPixmapFormats)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: Only some [%d] of the internal "
+ "pixmap formats [%d] match with external pixmap formats [%d] at tolerance [%u].\n",
+ total_matches, nxagentNumPixmapFormats, nxagentRemoteNumPixmapFormats, tolerance);
+ #endif
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForPixmapFormatsCompatibility: WARNING! Internally available "
+ "pixmap formats [%d] don't match with external pixmap formats [%d] "
+ "at tolerance [%u]. Only [%d] depth values matched.\n",
+ nxagentNumPixmapFormats, nxagentRemoteNumPixmapFormats, tolerance, total_matches);
+ #endif
+ }
+
+ return (ret);
+}
+
+static int nxagentInitAndCheckVisuals(int flexibility)
+{
+ /* FIXME: does this also need work? */
+ XVisualInfo viTemplate;
+ XVisualInfo *viList;
+ XVisualInfo *newVisuals;
+
+ long viMask;
+ int i, n;
+ int matched;
+ int compatible;
+ int viNumList;
+
+ compatible = 1;
+
+ viMask = VisualScreenMask;
+ viTemplate.screen = DefaultScreen(nxagentDisplay);
+ viTemplate.depth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ viList = XGetVisualInfo(nxagentDisplay, viMask, &viTemplate, &viNumList);
+
+ newVisuals = malloc(sizeof(XVisualInfo) * nxagentNumVisuals);
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ matched = 0;
+
+ for (n = 0; n < viNumList; n++)
+ {
+ if (nxagentCompareVisuals(nxagentVisuals[i], viList[n]) == 1)
+ {
+/*
+FIXME: Should the visual be ignored in this case?
+ We can flag the visuals with inverted masks,
+ and use this information to switch the masks
+ when contacting the remote X server.
+*/
+ if (nxagentVisuals[i].red_mask == viList[n].blue_mask &&
+ nxagentVisuals[i].blue_mask == viList[n].red_mask)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Red and blue mask inverted. "
+ "Forcing matching.\n");
+ #endif
+ }
+
+ matched = 1;
+
+ nxagentVisualHasBeenIgnored[i] = FALSE;
+
+ memcpy(newVisuals + i, viList + n, sizeof(XVisualInfo));
+
+ break;
+ }
+ }
+
+ if (matched == 0)
+ {
+ if (nxagentVisuals[i].class == DirectColor)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Ignoring not matched DirectColor visual.\n");
+ #endif
+
+ nxagentVisualHasBeenIgnored[i] = TRUE;
+
+ memcpy(newVisuals + i, nxagentVisuals + i, sizeof(XVisualInfo));
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitAndCheckVisuals: WARNING! Failed to match this visual:\n");
+ fprintf(stderr, "\tdepth = %d\n", nxagentVisuals[i].depth);
+ fprintf(stderr, "\tclass = %d\n", nxagentVisuals[i].class);
+ fprintf(stderr, "\tmask = (%ld,%ld,%ld)\n",
+ nxagentVisuals[i].red_mask,
+ nxagentVisuals[i].green_mask,
+ nxagentVisuals[i].blue_mask);
+ fprintf(stderr, "\tcolormap size = %d\n", nxagentVisuals[i].colormap_size);
+ fprintf(stderr, "\tbits_per_rgb = %d\n", nxagentVisuals[i].bits_per_rgb);
+ #endif
+
+ compatible = 0;
+
+ break;
+ }
+ }
+ }
+
+ XFree(viList);
+
+ if (compatible == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitAndCheckVisuals: New visuals match with old visuals.\n");
+ #endif
+
+ nxagentVisuals = newVisuals;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitAndCheckVisuals: New visuals don't match with old visuals.\n");
+ #endif
+
+ free(newVisuals);
+ }
+
+ return compatible;
+}
+
+static int nxagentCheckForColormapsCompatibility(int flexibility)
+{
+ /* FIXME: does this also need work? */
+ if (nxagentNumDefaultColormaps == nxagentNumDefaultColormapsRecBackup)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckForColormapsCompatibility: Number of new colormaps [%d] "
+ "matches with old colormaps.\n", nxagentNumDefaultColormaps);
+ #endif
+
+ return 1;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckForColormapsCompatibility: WARNING! Number of new colormaps [%d] "
+ "doesn't match with old colormaps [%d].\n", nxagentNumDefaultColormaps,
+ nxagentNumDefaultColormapsRecBackup);
+ #endif
+
+ return 0;
+ }
+}
+
+Bool nxagentReconnectDisplay(void *p0)
+{
+ int i;
+ int flexibility = *(int*)p0;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_DISPLAY_DEBUG)
+ fprintf(stderr, "nxagentReconnectDisplay\n");
+ #endif
+
+ if (reconnectDisplayState)
+ {
+ fprintf(stderr, "nxagentReconnectDisplay: Trying to reconnect a session "
+ "uncleanly disconnected\n");
+
+ return False;
+ }
+
+ /*
+ * Reset the values to their defaults.
+ */
+
+ nxagentPackMethod = -1;
+ nxagentPackQuality = -1;
+ nxagentSplitThreshold = -1;
+
+ nxagentRemoteMajor = -1;
+
+ nxagentInstallSignalHandlers();
+
+ nxagentInstallDisplayHandlers();
+
+ nxagentDisplay = nxagentInternalOpenDisplay(nxagentDisplayName);
+
+ nxagentPostInstallSignalHandlers();
+
+ nxagentPostInstallDisplayHandlers();
+
+ if (nxagentDisplay == NULL)
+ {
+ nxagentSetReconnectError(FAILED_RESUME_DISPLAY_ALERT,
+ "Couldn't open the display.");
+
+ return FALSE;
+ }
+
+ nxagentAddXConnection();
+
+ /*
+ * Display is now open.
+ */
+
+ reconnectDisplayState = OPENED;
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ fprintf(stderr, "Display: Open of the display finished with time [%d] ms.\n",
+ GetTimeInMillis() - startTime);
+
+ #endif
+
+ if (nxagentCheckForDefaultDepthCompatibility() == 0)
+ {
+ nxagentSetReconnectError(FAILED_RESUME_DISPLAY_ALERT,
+ "Default display depth doesn't match.");
+
+ return FALSE;
+ }
+
+ nxagentUseNXTrans = nxagentPostProcessArgs(nxagentDisplayName, nxagentDisplay,
+ DefaultScreenOfDisplay(nxagentDisplay));
+
+ /*
+ * After processing the arguments all the
+ * timeout values have been set. Now we
+ * have to change the screen-saver timeout.
+ */
+
+ nxagentSetScreenSaverTime();
+
+ /*
+ * Init and compare the visuals.
+ */
+
+ if (nxagentInitAndCheckVisuals(flexibility) == FALSE)
+ {
+ nxagentSetReconnectError(FAILED_RESUME_VISUALS_ALERT,
+ "Couldn't restore the required visuals.");
+
+ return FALSE;
+ }
+
+ reconnectDisplayState = GOT_VISUAL_INFO;
+
+ nxagentSetDefaultVisual();
+
+ nxagentInitAlphaVisual();
+
+ /*
+ * Re-allocate the colormaps.
+ */
+
+ nxagentNumDefaultColormaps = nxagentNumVisuals;
+
+ nxagentDefaultColormaps = (Colormap *) realloc(nxagentDefaultColormaps,
+ nxagentNumDefaultColormaps * sizeof(Colormap));
+
+ if (nxagentDefaultColormaps == NULL)
+ {
+ FatalError("Can't allocate memory for the default colormaps\n");
+ }
+
+ reconnectDisplayState = ALLOC_DEF_COLORMAP;
+
+ for (i = 0; i < nxagentNumDefaultColormaps; i++)
+ {
+ if (nxagentVisualHasBeenIgnored[i])
+ {
+ nxagentDefaultColormaps[i] = (XID)0;
+ }
+ else
+ {
+ nxagentDefaultColormaps[i] = XCreateColormap(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ nxagentVisuals[i].visual,
+ AllocNone);
+ }
+ }
+
+ nxagentCheckForColormapsCompatibility(flexibility);
+
+ /*
+ * Check the display depth.
+ */
+
+ nxagentInitDepths();
+
+ reconnectDisplayState = GOT_DEPTH_LIST;
+
+ if (nxagentCheckForDepthsCompatibility() == 0)
+ {
+ nxagentSetReconnectError(FAILED_RESUME_DEPTHS_ALERT,
+ "Couldn't restore all the required depths.");
+
+ return False;
+ }
+
+ /*
+ * nxagentPixmapFormats and nxagentRemotePixmapFormats
+ * will be reallocated in nxagentInitPixmapFormats().
+ */
+
+ if (nxagentPixmapFormats != NULL)
+ {
+ XFree(nxagentPixmapFormats);
+
+ nxagentPixmapFormats = NULL;
+ }
+
+ if (nxagentRemotePixmapFormats != NULL)
+ {
+ XFree(nxagentRemotePixmapFormats);
+
+ nxagentRemotePixmapFormats = NULL;
+ }
+
+ /*
+ * Check if all the required pixmap
+ * formats are supported.
+ */
+
+ nxagentInitPixmapFormats();
+
+ if (nxagentCheckForPixmapFormatsCompatibility() == 0)
+ {
+ nxagentSetReconnectError(FAILED_RESUME_PIXMAPS_ALERT,
+ "Couldn't restore all the required pixmap formats.");
+
+ return False;
+ }
+
+ reconnectDisplayState = GOT_PIXMAP_FORMAT_LIST;
+
+ /*
+ * Create a pixmap for each depth matching the
+ * local supported formats with format available
+ * on the remote display.
+ */
+
+ nxagentSetDefaultDrawables();
+
+ #ifdef RENDER
+
+ if (nxagentRenderEnable)
+ {
+ nxagentRenderExtensionInit();
+ }
+
+ if (nxagentRenderEnableRecBackup != nxagentRenderEnable)
+ {
+ nxagentRenderEnable = nxagentRenderEnableRecBackup;
+
+ nxagentSetReconnectError(FAILED_RESUME_RENDER_ALERT,
+ "Render extension not available or incompatible version.");
+
+ return False;
+ }
+
+ #endif
+
+ nxagentBlackPixel = BlackPixel(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ nxagentWhitePixel = WhitePixel(nxagentDisplay, DefaultScreen(nxagentDisplay));
+
+ /*
+ * Initialize the agent's event mask that will be requested
+ * for the root or all the top level windows. If the nested
+ * window is a child of an existing window we will need to
+ * receive StructureNotify events. If we are going to manage
+ * the changes in root window's visibility we'll also need
+ * VisibilityChange events.
+ */
+
+ nxagentInitDefaultEventMask();
+
+ nxagentBitmapGC = XCreateGC(nxagentDisplay, nxagentDefaultDrawables[1], 0L, NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectDisplay: Going to create agent's confine window.\n");
+ #endif
+
+ nxagentConfineWindow = XCreateWindow(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ 0, 0, 1, 1, 0, 0,
+ InputOnly,
+ CopyFromParent,
+ 0L, NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectDisplay: Created agent's confine window with id [%ld].\n",
+ nxagentConfineWindow);
+ #endif
+
+ nxagentLogoDepth = DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay));
+
+ nxagentLogoBlack = 0x000000;
+ nxagentLogoRed = 0xff0000;
+ nxagentLogoWhite = 0xffffff;
+ nxagentLogoGray = 0x222222;
+
+ useXpmIcon = nxagentMakeIcon(nxagentDisplay, &nxagentIconPixmap, &nxagentIconShape);
+
+ /*
+ * All went fine. We can continue
+ * handling our clients.
+ */
+
+ reconnectDisplayState = EVERYTHING_DONE;
+
+ return True;
+}
+
+void nxagentAddXConnection()
+{
+ int fd = XConnectionNumber(nxagentDisplay);
+
+ nxagentXConnectionNumber = fd;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddXConnection: Adding the X connection [%d] "
+ "to the device set.\n", nxagentXConnectionNumber);
+ #endif
+
+ SetNotifyFd(XConnectionNumber(nxagentDisplay), nxagentNotifyConnection, X_NOTIFY_READ, NULL);
+}
+
+void nxagentRemoveXConnection()
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemoveXConnection: Removing the X connection [%d] "
+ "from the device set.\n", nxagentXConnectionNumber);
+ #endif
+
+ RemoveNotifyFd(nxagentXConnectionNumber);
+}
+
+/*
+ * Force an I/O error and wait until the NX trans-
+ * port is gone. It must be called before suspend-
+ * ing or terminating a session to ensure that the
+ * NX transport is terminated first.
+ */
+
+void nxagentWaitDisplay()
+{
+ /*
+ * Disable the smart scheduler's interrupts.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWaitDisplay: Stopping the smart schedule timer.\n");
+ #endif
+
+ nxagentStopTimer();
+
+ if (nxagentDisplay != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitDisplay: Going to shutdown the X connection [%d].\n",
+ nxagentXConnectionNumber);
+ #endif
+
+ NXForceDisplayError(nxagentDisplay);
+
+ XSync(nxagentDisplay, 0);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitDisplay: Going to wait for the NX transport.\n");
+ #endif
+
+ NXTransDestroy(NX_FD_ANY);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitDisplay: The NX transport is not running.\n");
+ #endif
+
+ /*
+ * Be sure the signal handlers are
+ * in a known state.
+ */
+
+ nxagentResetSignalHandlers();
+}
+
+/*
+ * This has not to do with the remote display but
+ * with the X server that the agent is impersonating.
+ * We have it here to be consistent with the other
+ * cleanup procedures which have mainly to do with
+ * the Xlib display connection.
+ */
+
+void nxagentAbortDisplay()
+{
+ /*
+ * Be sure the X server socket in .X11-unix is
+ * deleted otherwise other users may to become
+ * unable to run a session on the same display.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAbortDisplay: Cleaning up the X server sockets.\n");
+ #endif
+
+ CloseWellKnownConnections();
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Display.h b/nx-X11/programs/Xserver/hw/nxagent/Display.h
new file mode 100644
index 000000000..759b0de35
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Display.h
@@ -0,0 +1,178 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Display_H__
+#define __Display_H__
+
+#define MAXDEPTH 32
+#define MAXVISUALSPERDEPTH 256
+
+extern Display *nxagentDisplay;
+extern Display *nxagentShadowDisplay;
+extern XVisualInfo *nxagentVisuals;
+extern int nxagentNumVisuals;
+extern int nxagentDefaultVisualIndex;
+extern Colormap *nxagentDefaultColormaps;
+extern int nxagentNumDefaultColormaps;
+extern int *nxagentDepths;
+extern int nxagentNumDepths;
+extern XPixmapFormatValues *nxagentPixmapFormats;
+extern int nxagentNumPixmapFormats;
+extern Pixel nxagentBlackPixel;
+extern Pixel nxagentWhitePixel;
+extern Drawable nxagentDefaultDrawables[MAXDEPTH + 1];
+extern Pixmap nxagentScreenSaverPixmap;
+
+/*
+ * The "confine" window is used in nxagentConstrainCursor().
+ * We are currently overriding the original Xnest behaviour
+ * and just skip the "constrain" stuff.
+ */
+
+extern Window nxagentConfineWindow;
+
+/*
+ * Keyboard and pointer are handled as they were hardware
+ * devices, that is we translate the key codes according to
+ * our own transcripts. We inherit this behaviour from Xnest.
+ * The following mask will contain the event mask selected
+ * for the root window. All the keyboard and pointer events
+ * are enqueued to the mi that translates and posts them to
+ * managed clients.
+ */
+
+extern unsigned long nxagentEventMask;
+
+void nxagentOpenDisplay(int argc, char *argv[]);
+void nxagentWaitDisplay(void);
+void nxagentCloseDisplay(void);
+void nxagentAbortDisplay(void);
+
+void nxagentAddXConnection(void);
+void nxagentRemoveXConnection(void);
+
+Bool nxagentXServerGeometryChanged(void);
+
+/*
+ * Create the default drawables.
+ */
+
+void nxagentGetDepthsAndPixmapFormats(void);
+void nxagentSetDefaultDrawables(void);
+
+extern Bool nxagentTrue24;
+
+void nxagentBackupDisplayInfo(void);
+void nxagentCleanupBackupDisplayInfo(void);
+
+void nxagentInstallDisplayHandlers(void);
+void nxagentPostInstallDisplayHandlers(void);
+void nxagentResetDisplayHandlers(void);
+
+void nxagentInstallSignalHandlers(void);
+void nxagentPostInstallSignalHandlers(void);
+void nxagentResetSignalHandlers(void);
+
+void nxagentDisconnectDisplay(void);
+Bool nxagentReconnectDisplay(void *p0);
+
+/*
+ * Deal with the smart scheduler.
+ */
+
+#if HAVE_SETITIMER
+#define nxagentInitTimer() \
+\
+ SmartScheduleInit();
+
+#define nxagentStopTimer() \
+\
+ SmartScheduleStopTimer(); \
+
+#define nxagentStartTimer() \
+\
+ SmartScheduleStartTimer();
+
+#define nxagentDisableTimer() \
+\
+ SmartScheduleStopTimer(); \
+ SmartScheduleSignalEnable = FALSE;
+#else
+#define nxagentInitTimer()
+#define nxagentStopTimer()
+#define nxagentStartTimer()
+#define nxagentDisableTimer()
+#endif /* HAVE_SETITIMER */
+
+/*
+ * File descriptor currently used by
+ * Xlib for the agent display.
+ */
+
+extern int nxagentXConnectionNumber;
+
+/*
+ * File descriptor currently used by
+ * Xlib for the agent shadow display.
+ */
+
+extern int nxagentShadowXConnectionNumber;
+
+int nxagentServerOrder(void);
+
+int nxagentGetDataRate(void);
+
+#define nxagentClientOrder(client) \
+ ((client)->swapped ? !nxagentServerOrder() : nxagentServerOrder())
+
+/*
+ * Terminate the agent after the next
+ * dispatch loop.
+ */
+
+#define nxagentTerminateSession() \
+ do \
+ { \
+ dispatchException |= DE_TERMINATE; \
+ \
+ isItTimeToYield = TRUE; \
+ } \
+ while (0)
+
+#endif /* __Display_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Drawable.c b/nx-X11/programs/Xserver/hw/nxagent/Drawable.c
new file mode 100644
index 000000000..917f460ba
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.c
@@ -0,0 +1,3308 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "dixstruct.h"
+#include "../../fb/fb.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Trap.h"
+#include "Image.h"
+#include "Drawable.h"
+#include "Client.h"
+#include "Visual.h"
+#include "Events.h"
+#include "GCs.h"
+#include "Utils.h"
+#include "Handlers.h"
+#include "Pixels.h"
+#include "Reconnect.h"
+#include "GCOps.h"
+
+#include "compext/Compext.h"
+
+#include "mibstorest.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * The list of rectangles composing a region
+ * s returned by nxagentGetOptimizedRegion-
+ * Boxes() instead of RegionRects().
+ */
+
+#define USE_OPTIMIZED_BOXES
+
+/*
+ * The rectangles composing a region are de-
+ * fragmented to reduce the number of synch-
+ * ronizing PutImage's.
+ */
+
+#define ADVANCED_BOXES_DEFRAG
+
+/*
+ * If defined, send the XClearArea at the end
+ * of the loop synchronizing the shadow pixmap.
+ * In this way, large images can be splitted but
+ * the user will see more updates togheter.
+ */
+
+#undef COLLECTED_UPDATES
+
+#ifdef ADVANCED_BOXES_DEFRAG
+#define INCLUDE_MARGIN 10
+#endif
+
+struct nxagentExposeBackground
+{
+ PixmapPtr pBackground;
+ RegionPtr pExpose;
+};
+
+RESTYPE RT_NX_CORR_BACKGROUND;
+RESTYPE RT_NX_CORR_WINDOW;
+RESTYPE RT_NX_CORR_PIXMAP;
+
+int nxagentCorruptedPixmaps = 0;
+int nxagentCorruptedWindows = 0;
+int nxagentCorruptedBackgrounds = 0;
+
+int nxagentForceSynchronization = 0;
+
+_nxagentSynchronizationRec nxagentSynchronization = { (DrawablePtr) NULL, 0, 0, 0, 0, 0 };
+
+RegionPtr nxagentDeferredBackgroundExposures = NullRegion;
+
+/*
+ * Predicate functions used to synchronize the
+ * content of the remote drawable with the data
+ * stored in the virtual frame-buffer.
+ */
+
+void nxagentSynchronizeDrawablePredicate(void *p0, XID x1, void *p2);
+void nxagentExposeBackgroundPredicate(void *p0, XID x1, void *p2);
+
+/*
+ * Imported from NXresource.c
+ */
+
+extern int nxagentFindClientResource(int, RESTYPE, void *);
+
+unsigned long nxagentGetColor(DrawablePtr pDrawable, int xPixel, int yPixel);
+unsigned long nxagentGetDrawableColor(DrawablePtr pDrawable);
+unsigned long nxagentGetRegionColor(DrawablePtr pDrawable, RegionPtr pRegion);
+
+int nxagentSkipImage = 0;
+
+static int nxagentTooManyImageData(void)
+{
+ unsigned int r;
+ unsigned int limit;
+
+ limit = nxagentOption(ImageRateLimit);
+
+ r = nxagentGetDataRate() / 1000;
+
+ #ifdef TEST
+ if (r > limit)
+ {
+ fprintf(stderr, "Warning: Current bit rate is: %u kB/s.\n", r);
+ }
+ #endif
+
+ return (r > limit);
+}
+
+int nxagentSynchronizeDrawable(DrawablePtr pDrawable, int wait, unsigned int breakMask, WindowPtr owner)
+{
+ int result;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ if (nxagentLosslessTrap == 0)
+ {
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawable: Drawable [%s][%p] with id [%ld] already "
+ "synchronized.\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, pDrawable -> id);
+ #endif
+
+ return 0;
+ }
+ }
+
+ /*
+ * What we want here is to avoid drawing on the
+ * framebuffer and just perform the operation
+ * on the real X server. This is the purpose of
+ * the FB trap. At the same time we also want
+ * to avoid a split, so that the image will be
+ * transferred in a single operation.
+ */
+
+ nxagentFBTrap = 1;
+
+ nxagentSplitTrap = 1;
+
+ result = nxagentSynchronizeDrawableData(pDrawable, breakMask, owner);
+
+ nxagentSplitTrap = 0;
+
+ nxagentFBTrap = 0;
+
+ if (wait == DO_WAIT && nxagentSplitResource(pDrawable) != NULL)
+ {
+ nxagentWaitDrawable(pDrawable);
+ }
+
+ #ifdef TEST
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ fprintf(stderr, "nxagentSynchronizeDrawable: Drawable %s [%p] with id [%ld] now synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable, pDrawable -> id);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentSynchronizeDrawable: Drawable %s [%p] with id [%ld] not fully synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable, pDrawable -> id);
+ }
+
+ #endif
+
+ return result;
+}
+
+int nxagentSynchronizeDrawableData(DrawablePtr pDrawable, unsigned int breakMask, WindowPtr owner)
+{
+ int width, height, depth, length;
+ unsigned int leftPad, format;
+
+ char *data = NULL;
+ DrawablePtr pSrcDrawable;
+ GCPtr pGC;
+
+ int success;
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ leftPad = 0;
+
+ width = pDrawable -> width;
+ height = pDrawable -> height;
+ depth = pDrawable -> depth;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawableData: Synchronizing drawable (%s) with geometry [%d][%d][%d].\n",
+ nxagentDrawableType(pDrawable), width, height, depth);
+ #endif
+
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ length = nxagentImageLength(width, height, format, leftPad, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ success = 0;
+
+ goto nxagentSynchronizeDrawableDataEnd;
+ }
+
+ pSrcDrawable = (pDrawable -> type == DRAWABLE_PIXMAP ?
+ ((DrawablePtr) nxagentVirtualPixmap((PixmapPtr) pDrawable)) :
+ pDrawable);
+
+ /*
+ * Synchronize the whole pixmap if we need
+ * to download a fresh copy with lossless
+ * compression turned off.
+ */
+
+ if (nxagentLosslessTrap == 1)
+ {
+ pGC = nxagentGetGraphicContext(pDrawable);
+
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to get the temporary GC.\n");
+ #endif
+
+ success = 0;
+
+ goto nxagentSynchronizeDrawableDataFree;
+ }
+
+ ValidateGC(pDrawable, pGC);
+
+ fbGetImage(pSrcDrawable, 0, 0,
+ width, height, format, AllPlanes, data);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawableData: Forcing synchronization of "
+ "pixmap at [%p] with lossless compression.\n", (void *) pDrawable);
+ #endif
+
+ nxagentPutImage(pDrawable, pGC, depth, 0, 0,
+ width, height, leftPad, format, data);
+
+ success = 1;
+
+ goto nxagentSynchronizeDrawableDataFree;
+ }
+ else if (nxagentReconnectTrap == 1)
+ {
+ /*
+ * The pixmap data is not synchronized unless
+ * we need it. We noticed we have to reconnect
+ * the pixmaps used by the GC's clip mask.
+ * The other data will be synchronized on demand.
+ */
+
+ if (pDrawable -> depth == 1)
+ {
+ #ifdef TEST
+
+ if (nxagentReconnectTrap == 1)
+ {
+ static int totalLength;
+ static int totalReconnectedPixmaps;
+
+ totalLength += length;
+ totalReconnectedPixmaps++;
+
+ fprintf(stderr, "nxagentSynchronizeDrawableData: Reconnecting pixmap at [%p] [%dx%d] "
+ "Depth [%d] Size [%d]. Total size [%d]. Total reconnected pixmaps [%d].\n",
+ (void *) pDrawable, width, height, depth, length,
+ totalLength, totalReconnectedPixmaps);
+ }
+
+ #endif
+
+ pGC = nxagentGetGraphicContext(pDrawable);
+
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSynchronizeDrawableData: WARNING! Failed to create the temporary GC.\n");
+ #endif
+
+ success = 0;
+
+ goto nxagentSynchronizeDrawableDataFree;
+ }
+
+ ValidateGC(pDrawable, pGC);
+
+ fbGetImage(pSrcDrawable, 0, 0,
+ width, height, format, AllPlanes, data);
+
+ nxagentPutImage(pDrawable, pGC, depth, 0, 0,
+ width, height, leftPad, format, data);
+
+ success = 1;
+
+ goto nxagentSynchronizeDrawableDataFree;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawableData: Skipping synchronization of "
+ "pixmap at [%p][%p] during reconnection.\n", (void *) pDrawable, (void*) nxagentVirtualPixmap((PixmapPtr)pDrawable));
+ #endif
+
+ nxagentMarkCorruptedRegion(pDrawable, NullRegion);
+
+ success = 1;
+
+ goto nxagentSynchronizeDrawableDataFree;
+ }
+ }
+ }
+
+ /*
+ * By calling this function with the NullRegion
+ * as parameter we are requesting to synchro-
+ * nize the full visible corrupted region of
+ * the drawable.
+ */
+
+ success = nxagentSynchronizeRegion(pDrawable, NullRegion, breakMask, owner);
+
+nxagentSynchronizeDrawableDataFree:
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+
+nxagentSynchronizeDrawableDataEnd:
+
+ return success;
+}
+
+/*
+ * If pRegion is NullRegion, all the viewable
+ * corrupted region will be synchronized.
+ */
+
+int nxagentSynchronizeRegion(DrawablePtr pDrawable, RegionPtr pRegion, unsigned int breakMask, WindowPtr owner)
+{
+ GCPtr pGC;
+ DrawablePtr pSrcDrawable;
+ BoxPtr pBox;
+ RegionPtr clipRegion;
+
+ RegionRec tileRegion;
+ RegionRec exposeRegion;
+ BoxRec box;
+ BoxRec tileBox;
+
+ #ifdef COLLECTED_UPDATES
+ RegionRec collectedUpdates;
+ #endif
+
+ char *data;
+
+ int nBox;
+ int x, y;
+ int w, h;
+ int extentWidth, extentHeight;
+ int tileWidth, tileHeight;
+ int length, format, leftPad;
+ int i;
+ int saveTrap;
+ int success;
+ int useStoredBitmap;
+
+ unsigned long now;
+ unsigned long elapsedTime;
+
+
+ leftPad = 0;
+ success = 0;
+ data = NULL;
+ pGC = NULL;
+ clipRegion = NullRegion;
+
+ #ifdef COLLECTED_UPDATES
+ RegionInit(&collectedUpdates, NullBox, 1);
+ #endif
+
+ RegionInit(&exposeRegion, NullBox, 1);
+
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap &&
+ nxagentDrawableStatus((DrawablePtr) nxagentDrawableBitmap(pDrawable)) == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Drawable [%s] at [%p] has an already synchronized "
+ "bitmap at [%p].\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, (void *) nxagentDrawableBitmap(pDrawable));
+ #endif
+
+ nxagentDestroyDrawableBitmap(pDrawable);
+ }
+
+ /*
+ * The stored bitmap may be used if we
+ * are going to synchronize the full
+ * drawable.
+ */
+
+ useStoredBitmap = (nxagentDrawableBitmap(pDrawable) != NullPixmap && pRegion == NullRegion);
+
+ if (useStoredBitmap != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Drawable [%s] at [%p] has a synchronization bitmap at [%p] "
+ "[%d,%d,%d,%d] with [%ld] rects.\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, (void *) nxagentDrawableBitmap(pDrawable),
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2,
+ RegionNumRects(nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable))));
+ #endif
+
+ clipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height);
+
+ /*
+ * Intersecting the viewable region of the
+ * drawable with the region remaining from
+ * a previous loop.
+ */
+
+ RegionIntersect(clipRegion, clipRegion,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)));
+
+ /*
+ * The bitmap regions used in the synchro-
+ * nizations are only those corrupted also
+ * on the drawable. In this way, if we put
+ * a tile in a bad position (e.g. if the
+ * corrupted region moves), the next synch-
+ * ronization will fix the error.
+ */
+
+ RegionIntersect(clipRegion, clipRegion,
+ nxagentCorruptedRegion(pDrawable));
+
+ /*
+ * The bitmap to synchronize is clipped.
+ */
+
+ if (RegionNil(clipRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: The bitmap region [%d,%d,%d,%d] is not viewable. "
+ "Destroying it.\n", clipRegion -> extents.x1, clipRegion -> extents.y1,
+ clipRegion -> extents.x2, clipRegion -> extents.y2);
+ #endif
+
+ nxagentDestroyDrawableBitmap(pDrawable);
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ /*
+ * Using the saved bitmap as source, instead
+ * of the drawable itself.
+ */
+
+ pSrcDrawable = ((DrawablePtr) nxagentVirtualPixmap(nxagentDrawableBitmap(pDrawable)));
+ }
+ else
+ {
+ if (pRegion != NullRegion && RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Region [%d,%d,%d,%d] is nil. Skipping synchronization.\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2);
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: The [%s] at [%p] is already synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ /*
+ * Creating a region containing the viewable
+ * area of drawable.
+ */
+
+ clipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height);
+
+ /*
+ * If the corrupted region is not viewable, we
+ * can skip the synchronization.
+ */
+
+ RegionIntersect(clipRegion, clipRegion, nxagentCorruptedRegion(pDrawable));
+
+ if (RegionNil(clipRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: The corrupted region [%d,%d,%d,%d] is not viewable "
+ "on [%s] at [%p]. Skipping the synchronization.\n", clipRegion -> extents.x1,
+ clipRegion -> extents.y1, clipRegion -> extents.x2, clipRegion -> extents.y2,
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ /*
+ * We can skip the synchronization if the re-
+ * quested region is not corrupted. Specifying
+ * a NullRegion as parameter, all the viewable
+ * corrupted region will be synchronized.
+ */
+
+ if (pRegion != NullRegion)
+ {
+ RegionIntersect(clipRegion, clipRegion, pRegion);
+
+ if (RegionNil(clipRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Region requested [%d,%d,%d,%d] already "
+ "synchronized on [%s] at [%p].\n", pRegion -> extents.x1,
+ pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2,
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+ }
+
+ pSrcDrawable = (pDrawable -> type == DRAWABLE_PIXMAP ?
+ ((DrawablePtr) nxagentVirtualPixmap((PixmapPtr) pDrawable)) :
+ pDrawable);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronizing region with coordinates [%d,%d,%d,%d] "
+ "on [%s] at [%p].\n", clipRegion -> extents.x1, clipRegion -> extents.y1,
+ clipRegion -> extents.x2, clipRegion -> extents.y2,
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ saveTrap = nxagentGCTrap;
+
+ nxagentGCTrap = 0;
+
+ nxagentFBTrap = 1;
+
+ nxagentSplitTrap = 1;
+
+ pGC = nxagentGetGraphicContext(pDrawable);
+
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to create the temporary GC.\n");
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ ValidateGC(pDrawable, pGC);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Going to synchronize [%ld] rects of [%s] at [%p].\n",
+ RegionNumRects(clipRegion), nxagentDrawableType(pDrawable), (void *) pDrawable);
+
+ fprintf(stderr, "nxagentSynchronizeRegion: Extents geometry [%d,%d,%d,%d].\n",
+ clipRegion -> extents.x1, clipRegion -> extents.y1, clipRegion -> extents.x2, clipRegion -> extents.y2);
+
+ fprintf(stderr, "nxagentSynchronizeRegion: Drawable geometry [%d,%d,%d,%d].\n",
+ pDrawable -> x, pDrawable -> y, pDrawable -> width, pDrawable -> height);
+ #endif
+
+ /*
+ * We are going to synchronize the corrupted
+ * area, so we use the corrupted extents as
+ * maximum size of the image data. It's im-
+ * portant to avoid using the drawable size,
+ * because in case of a huge window it had to
+ * result in a failed data memory allocation.
+ */
+
+ extentWidth = clipRegion -> extents.x2 - clipRegion -> extents.x1;
+ extentHeight = clipRegion -> extents.y2 - clipRegion -> extents.y1;
+
+ w = tileWidth = (nxagentOption(TileWidth) > extentWidth ? extentWidth : nxagentOption(TileWidth));
+ h = tileHeight = (nxagentOption(TileHeight) > extentHeight ? extentHeight : nxagentOption(TileHeight));
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSynchronizeRegion: Using tiles of size [%dx%d].\n", tileWidth, tileHeight);
+ #endif
+
+ data = nxagentAllocateImageData(w, h, pDrawable -> depth, &length, &format);
+
+ if (data == NULL)
+ {
+ #ifdef WARNING
+
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to allocate memory for synchronization.\n");
+
+ /*
+ * Print detailed informations if the
+ * image length is zero.
+ */
+
+ if (length == 0)
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: Drawable [%s] at [%p] with region geometry [%d][%d,%d,%d,%d].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable, RegionNumRects(clipRegion),
+ clipRegion -> extents.x1, clipRegion -> extents.y1,
+ clipRegion -> extents.x2, clipRegion -> extents.y2);
+ }
+
+ #endif
+
+ goto nxagentSynchronizeRegionFree;
+ }
+
+ #ifndef USE_OPTIMIZED_BOXES
+
+ pBox = RegionRects(clipRegion);
+
+ #else
+
+ pBox = nxagentGetOptimizedRegionBoxes(clipRegion);
+
+ #endif /* USE_OPTIMIZED_BOXES */
+
+ nBox = RegionNumRects(clipRegion);
+
+ now = GetTimeInMillis();
+
+ nxagentSynchronization.abort = 0;
+
+ /*
+ * Going to split the updated region into small blocks.
+ */
+
+ for (i = 0; i < nBox; i++)
+ {
+ #ifdef USE_OPTIMIZED_BOXES
+
+ if (pBox[i].x1 == 0 && pBox[i].y1 == 0 &&
+ pBox[i].x2 == 0 && pBox[i].y2 == 0)
+ {
+ continue;
+ }
+
+ #endif
+
+ box = pBox[i];
+
+ for (y = box.y1; y < box.y2; y += h)
+ {
+ h = MIN(box.y2 - y, tileHeight);
+
+ for (x = box.x1; x < box.x2; x += w)
+ {
+ w = MIN(box.x2 - x, tileWidth);
+
+ /*
+ * FIXME: This should not occur.
+ */
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef WARNING
+
+ if (pDrawable -> type == DRAWABLE_WINDOW && pSrcDrawable != pDrawable)
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Trying to synchronize "
+ "the clean drawable type [%d] at [%p] with source at [%p].\n",
+ pDrawable -> type, (void *) pDrawable, (void *) pSrcDrawable);
+ }
+
+ #endif
+
+ goto nxagentSynchronizeRegionStop;
+ }
+
+ if (canBreakOnTimeout(breakMask))
+ {
+ /*
+ * Abort the synchronization loop if it
+ * lasts for more than DeferTimeout
+ * milliseconds.
+ */
+
+ elapsedTime = GetTimeInMillis() - now;
+
+ if (elapsedTime > nxagentOption(DeferTimeout))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with "
+ "[%lu] ms elapsed.\n", elapsedTime);
+ #endif
+
+ nxagentSynchronization.abort = 1;
+
+ goto nxagentSynchronizeRegionStop;
+ }
+ }
+
+ /*
+ * Abort the loop if we go out of bandwidth.
+ */
+
+ if (breakOnCongestionDrawable(breakMask, pDrawable) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with "
+ "congestion [%d] blocking [%d].\n", nxagentCongestion,
+ nxagentBlocking);
+ #endif
+
+ nxagentSynchronization.abort = 1;
+
+ goto nxagentSynchronizeRegionStop;
+ }
+
+ /*
+ * Abort the loop if the display blocks.
+ */
+
+ if (breakOnBlocking(breakMask) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with "
+ "blocking [%d] congestion [%d].\n", nxagentBlocking,
+ nxagentCongestion);
+ #endif
+
+ nxagentSynchronization.abort = 1;
+
+ goto nxagentSynchronizeRegionStop;
+ }
+
+ tileBox.x1 = x;
+ tileBox.y1 = y;
+ tileBox.x2 = x + w;
+ tileBox.y2 = y + h;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSynchronizeRegion: Going to synchronize tile [%d,%d,%d,%d].\n",
+ tileBox.x1, tileBox.y1, tileBox.x2, tileBox.y2);
+ #endif
+
+ nxagentGetImage(pSrcDrawable, x, y, w, h, format, AllPlanes, data);
+
+ /*
+ * Going to unmark the synchronized
+ * region.
+ */
+
+ RegionInit(&tileRegion, &tileBox, 1);
+
+ RegionUnion(&exposeRegion, &exposeRegion, &tileRegion);
+
+ #ifdef COLLECTED_UPDATES
+ RegionAppend(&collectedUpdates, &tileRegion);
+ #endif
+
+ if (useStoredBitmap != 0)
+ {
+ /*
+ * When a bitmap's tile is synchronized,
+ * we can clear the corresponding region.
+ * We can't use the nxagentUnmarkCorrupted-
+ * Region because we have not a resource
+ * associated to this pixmap.
+ */
+
+ RegionSubtract(nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)),
+ nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), &tileRegion);
+
+ /*
+ * The drawable's corrupted region can
+ * be cleared if the bitmap's tile data
+ * matches the drawable's content at the
+ * same position.
+ */
+
+ if (nxagentDrawableStatus(pDrawable) == NotSynchronized)
+ {
+ char *cmpData;
+
+ int cmpLength, cmpFormat;
+
+ cmpData = nxagentAllocateImageData(w, h, pDrawable -> depth, &cmpLength, &cmpFormat);
+
+ if (cmpData != NULL)
+ {
+ nxagentGetImage(pDrawable, x, y, w, h, format, AllPlanes, cmpData);
+
+ if (memcmp(data, cmpData, cmpLength) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Tile [%d,%d,%d,%d] matches drawable's data at same position.\n",
+ x, y, x + w, y + h);
+ #endif
+
+ nxagentUnmarkCorruptedRegion(pDrawable, &tileRegion);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentSynchronizeRegion: Tile [%d,%d,%d,%d] on drawable [%p] doesn't match.\n",
+ x, y, x + w, y + h, (void *) pDrawable);
+ }
+ #endif
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSynchronizeRegion: WARNING! Failed to allocate memory to compare tiles.\n");
+ #endif
+ }
+
+ if (cmpData != NULL)
+ {
+ free(cmpData);
+ }
+ }
+ }
+ else
+ {
+ nxagentUnmarkCorruptedRegion(pDrawable, &tileRegion);
+
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Going to clean bitmap at [%p] with newer data.\n",
+ (void *) nxagentDrawableBitmap(pDrawable));
+ #endif
+
+ RegionSubtract(nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)),
+ nxagentPixmapCorruptedRegion(nxagentDrawableBitmap(pDrawable)), &tileRegion);
+ }
+ }
+
+ /*
+ * Realize the image after comparing the
+ * source data with the bitmap data.
+ */
+
+ nxagentRealizeImage(pDrawable, pGC, pDrawable -> depth,
+ x, y, w, h, leftPad, format, data);
+
+ RegionUninit(&tileRegion);
+
+ #if !defined(COLLECTED_UPDATES)
+
+ if (owner != NULL)
+ {
+ if (nxagentOption(Shadow) == 1 &&
+ (nxagentOption(XRatio) != DONT_SCALE ||
+ nxagentOption(YRatio) != DONT_SCALE))
+ {
+ int scaledx;
+ int scaledy;
+ int scaledw;
+ int scaledh;
+
+ scaledx = nxagentScale(x, nxagentOption(XRatio));
+ scaledy = nxagentScale(y, nxagentOption(YRatio));
+
+ scaledw = nxagentScale(x + w, nxagentOption(XRatio)) - scaledx;
+ scaledh = nxagentScale(y + h, nxagentOption(YRatio)) - scaledy;
+
+ XClearArea(nxagentDisplay, nxagentWindow(owner), scaledx, scaledy, scaledw, scaledh, 0);
+ }
+ else
+ {
+ XClearArea(nxagentDisplay, nxagentWindow(owner), x, y, w, h, 0);
+ }
+ }
+
+ #endif /* #if !defined(COLLECTED_UPDATES) */
+
+ /*
+ * Abort the loop on the user's input.
+ * This is done here to check for events
+ * read after the flush caused by the
+ * PutImage.
+ */
+
+ nxagentDispatchHandler((ClientPtr) 0, 0, 0);
+
+ if (breakOnEvent(breakMask) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronization break with "
+ "new input events.\n");
+ #endif
+
+ nxagentSynchronization.abort = 1;
+
+ goto nxagentSynchronizeRegionStop;
+ }
+ }
+ }
+ }
+
+nxagentSynchronizeRegionStop:
+
+ nxagentSplitTrap = 0;
+
+ nxagentFBTrap = 0;
+
+ nxagentGCTrap = saveTrap;
+
+ success = 1;
+
+ if (nxagentOption(Shadow) == 0)
+ {
+ if (nxagentSynchronization.abort == 1)
+ {
+ /*
+ * Storing the pointer to the drawable we
+ * were synchronizing when the loop aborted.
+ * It is used in nxagentSynchronizeDrawable-
+ * Predicate.
+ */
+
+ nxagentSynchronization.pDrawable = pDrawable;
+ nxagentSynchronization.drawableType = pDrawable -> type;
+
+ if (nxagentDrawableBitmap(pDrawable) == NullPixmap)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Going to create the synchronization bitmap.\n");
+ #endif
+
+ nxagentCreateDrawableBitmap(pDrawable);
+ }
+ }
+ else
+ {
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeRegion: Synchronization loop finished. Going to destroy synchronization bitmap.\n");
+ #endif
+
+ nxagentDestroyDrawableBitmap(pDrawable);
+ }
+ }
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1 &&
+ RegionNil(&exposeRegion) == 0)
+ {
+ struct nxagentExposeBackground eb;
+
+ int i;
+
+ eb.pBackground = (PixmapPtr) pDrawable;
+ eb.pExpose = &exposeRegion;
+
+ for (i = 0; i < MAXCLIENTS; i++)
+ {
+ if (clients[i] != NULL)
+ {
+ FindClientResourcesByType(clients[i], RT_WINDOW,
+ nxagentExposeBackgroundPredicate, &eb);
+ }
+ }
+ }
+ }
+ #ifdef COLLECTED_UPDATES
+ else
+ {
+ if (owner != NULL)
+ {
+ int overlap = 0;
+
+ RegionValidate(&collectedUpdates, &overlap);
+
+ for (i = 0; i < RegionNumRects(&collectedUpdates); i++)
+ {
+ x = RegionRects(&collectedUpdates)[i].x1;
+ y = RegionRects(&collectedUpdates)[i].y1;
+ w = RegionRects(&collectedUpdates)[i].x2 - RegionRects(&collectedUpdates)[i].x1;
+ h = RegionRects(&collectedUpdates)[i].y2 - RegionRects(&collectedUpdates)[i].y1;
+
+ if (nxagentOption(Shadow) == 1 &&
+ (nxagentOption(XRatio) != DONT_SCALE ||
+ nxagentOption(YRatio) != DONT_SCALE))
+ {
+ int scaledx;
+ int scaledy;
+ int scaledw;
+ int scaledh;
+
+ scaledx = nxagentScale(x, nxagentOption(XRatio));
+ scaledy = nxagentScale(y, nxagentOption(YRatio));
+
+ scaledw = nxagentScale(x + w, nxagentOption(XRatio)) - scaledx;
+ scaledh = nxagentScale(y + h, nxagentOption(YRatio)) - scaledy;
+
+ XClearArea(nxagentDisplay, nxagentWindow(owner), scaledx, scaledy, scaledw, scaledh, 0);
+ }
+ else
+ {
+ XClearArea(nxagentDisplay, nxagentWindow(owner), x, y, w, h, 0);
+ }
+ }
+ }
+ }
+ #endif /* #ifdef COLLECTED_UPDATES */
+
+nxagentSynchronizeRegionFree:
+
+ if (clipRegion != NullRegion)
+ {
+ nxagentFreeRegion(pDrawable, clipRegion);
+ }
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+
+ RegionUninit(&exposeRegion);
+
+ #ifdef COLLECTED_UPDATES
+
+ RegionUninit(&collectedUpdates);
+
+ #endif /* #ifdef COLLECTED_UPDATES */
+
+ return success;
+}
+
+void nxagentSynchronizeBox(DrawablePtr pDrawable, BoxPtr pBox, unsigned int breakMask)
+{
+ RegionPtr pRegion;
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeBox: The [%s] at [%p] is already synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ if (pBox == NullBox)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeBox: Going to synchronize the whole [%s] at [%p].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ nxagentSynchronizeRegion(pDrawable, NullRegion, breakMask, NULL);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeBox: Going to create a region from box [%d,%d,%d,%d].\n",
+ pBox -> x1, pBox -> y1, pBox -> x2, pBox -> y2);
+ #endif
+
+ pRegion = nxagentCreateRegion(pDrawable, NULL, pBox -> x1, pBox -> y1,
+ pBox -> x2 - pBox -> x1, pBox -> y2 - pBox -> y1);
+
+
+ if (RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeBox: Resulting region [%d,%d,%d,%d] is nil. Skipping synchronization.\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2);
+ #endif
+
+ nxagentFreeRegion(pDrawable, pRegion);
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeBox: Going to synchronize the region [%d,%d,%d,%d] of "
+ "[%s] at [%p].\n", pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2,
+ pRegion -> extents.y2, nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ nxagentSynchronizeRegion(pDrawable, pRegion, breakMask, NULL);
+
+ nxagentFreeRegion(pDrawable, pRegion);
+ }
+}
+
+void nxagentSynchronizeDrawablePredicate(void *p0, XID x1, void *p2)
+{
+ DrawablePtr pDrawable = (DrawablePtr) p0;
+ unsigned int *breakMask = (unsigned int *) p2;
+
+ int shouldClearHiddenRegion = 1;
+
+ /*
+ * The nxagentSynchronization.abort propa-
+ * gates a break condition across the resour-
+ * ces loop, in order to block also the sub-
+ * sequent synchronizations.
+ */
+
+ if (nxagentSynchronization.abort == 1 ||
+ nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ return;
+ }
+
+ /*
+ * In order to implement a kind of round-robin
+ * synchronization, the previous incomplete
+ * drawable synchronization is saved to jump
+ * to the next resource available of same type.
+ */
+
+ if (nxagentSynchronization.pDrawable != NULL &&
+ pDrawable -> type == nxagentSynchronization.drawableType)
+ {
+ if (nxagentSynchronization.pDrawable != pDrawable)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping drawable [%s][%p] while looking "
+ "for last synchronized drawable [%p].\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, (void *) nxagentSynchronization.pDrawable);
+ #endif
+
+ return;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Last synchronized drawable [%p] found. "
+ "Skipping to the next resource.\n", (void *) nxagentSynchronization.pDrawable);
+ #endif
+
+ nxagentSynchronization.pDrawable = NULL;
+
+ return;
+ }
+ }
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ /*
+ * The pixmaps to be synchronized are those
+ * used as background or used as source of
+ * any deferred operations for at least 2
+ * times.
+ */
+
+ if (NXAGENT_SHOULD_SYNCHRONIZE_PIXMAP(pDrawable) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping pixmap at [%p] "
+ "with usage [%d] background [%d].\n", (void *) pDrawable,
+ nxagentPixmapUsageCounter((PixmapPtr) pDrawable),
+ nxagentIsCorruptedBackground((PixmapPtr) pDrawable));
+ #endif
+
+ return;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Synchronizing pixmap at [%p] "
+ "with usage [%d] background [%d].\n", (void *) pDrawable,
+ nxagentPixmapUsageCounter((PixmapPtr) pDrawable),
+ nxagentIsCorruptedBackground((PixmapPtr) pDrawable));
+ }
+ #endif
+ }
+ else if (NXAGENT_SHOULD_SYNCHRONIZE_WINDOW(pDrawable) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Skipping not visible window at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ if (shouldClearHiddenRegion == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Clearing out the not visible window "
+ "at [%p].\n", (void *) pDrawable);
+ #endif
+
+ nxagentCleanCorruptedDrawable(pDrawable);
+ }
+
+ return;
+ }
+
+ /*
+ * Postpone the synchronization if we went
+ * out of bandwidth or if the display blocks.
+ * The pixmap synchronization is more careful
+ * with bandwidth usage.
+ */
+
+/*
+FIXME: This condition sounds only as a
+ complication, as the break parameters
+ are already checked while synchroni-
+ zing the drawable.
+
+ if (breakOnCongestion(*breakMask) == 1 ||
+ (pDrawable -> type == DRAWABLE_PIXMAP &&
+ *breakMask != NEVER_BREAK && nxagentCongestion > 0))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: WARNING! Breaking the "
+ "synchronization with congestion [%d] blocking [%d].\n",
+ nxagentCongestion, nxagentBlocking);
+ #endif
+
+ nxagentSynchronization.abort = 1;
+
+ return;
+ }
+*/
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Synchronizing drawable [%s][%p] "
+ "with geometry (%dx%d).\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, pDrawable -> width, pDrawable -> height);
+
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Corrupted extents [%d,%d,%d,%d] "
+ "with [%ld] rects.\n", nxagentCorruptedRegion(pDrawable) -> extents.x1,
+ nxagentCorruptedRegion(pDrawable) -> extents.y1, nxagentCorruptedRegion(pDrawable) ->
+ extents.x2, nxagentCorruptedRegion(pDrawable) -> extents.y2,
+ RegionNumRects(nxagentCorruptedRegion(pDrawable)));
+ #endif
+
+ /*
+ * The stored bitmap is destroyed inside
+ * the synchronization loop, so we have
+ * to check here its presence to know if
+ * we can clear the dirty windows.
+ */
+
+ shouldClearHiddenRegion = (nxagentDrawableBitmap(pDrawable) == NullPixmap);
+
+ nxagentSynchronizeDrawable(pDrawable, DONT_WAIT, *breakMask, NULL);
+
+ if (nxagentDrawableStatus(pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Drawable [%s][%p] not fully synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ /*
+ * If the remaining corrupted region is on
+ * an hidden section (not viewable or outside
+ * of the pixmap's area) of a drawable,
+ * we can clear it.
+ */
+
+ if (nxagentSynchronization.abort == 0 &&
+ shouldClearHiddenRegion == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawablePredicate: Clearing out the remaining corrupted "
+ "[%s] at [%p].\n", nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ nxagentCleanCorruptedDrawable(pDrawable);
+ }
+ }
+}
+
+void nxagentSynchronizationLoop(unsigned int mask)
+{
+ unsigned int breakMask;
+
+ int doRoundRobin;
+
+/*
+FIXME: All drawables should be set as synchronized and
+ never marked as corrupted while the display is
+ down.
+*/
+
+ nxagentSkipImage = nxagentTooManyImageData();
+
+ if (nxagentOption(ImageRateLimit) && nxagentSkipImage)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeDrawable: Skipping due to bit rate limit reached.\n");
+ #endif
+
+ return;
+ }
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: WARNING! Not synchronizing the drawables "
+ "with the display down.\n");
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Synchronizing [%d] windows [%d] pixmaps "
+ "and [%d] backgrounds with mask [%u].\n", nxagentCorruptedWindows, nxagentCorruptedPixmaps,
+ nxagentCorruptedBackgrounds, mask);
+
+ fprintf(stderr, "nxagentSynchronizationLoop: Stored bitmaps [%d] windows [%d] pixmaps "
+ "and [%d] backgrounds.\n", nxagentSynchronization.windowBitmaps,
+ nxagentSynchronization.pixmapBitmaps, nxagentSynchronization.backgroundBitmaps);
+
+ fprintf(stderr, "nxagentSynchronizationLoop: Starting loops with congestion [%d] "
+ "blocking [%d].\n", nxagentCongestion, nxagentBlocking);
+ #endif
+
+ breakMask = mask;
+
+ /*
+ * The resource counter can be reset if we
+ * have not aborted the synchronization loop,
+ * if we are not skipping resources to do
+ * round-robin and if the bitmaps are all
+ * synchronized.
+ */
+
+ doRoundRobin = (nxagentSynchronization.pDrawable != NULL);
+
+ nxagentSynchronization.abort = 0;
+
+ /*
+ * Synchronize the windows.
+ */
+
+ if (NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_WINDOWS(mask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted window resources.\n");
+ #endif
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_WINDOW,
+ nxagentSynchronizeDrawablePredicate, &breakMask);
+
+ #ifdef TEST
+
+ if (nxagentSynchronization.abort == 0 &&
+ nxagentSynchronization.windowBitmaps == 0 &&
+ doRoundRobin == 0)
+ {
+ if (nxagentCorruptedWindows > 0)
+ {
+ fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] "
+ "corrupted windows.\n", nxagentCorruptedWindows);
+ }
+
+ nxagentCorruptedWindows = 0;
+ }
+
+ #endif
+ }
+
+ /*
+ * Synchronize the backgrounds.
+ */
+
+ if (nxagentSynchronization.abort == 0 &&
+ NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_BACKGROUNDS(mask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted background resources.\n");
+ #endif
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_BACKGROUND,
+ nxagentSynchronizeDrawablePredicate, &breakMask);
+
+ #ifdef TEST
+
+ if (nxagentSynchronization.abort == 0 &&
+ nxagentSynchronization.backgroundBitmaps == 0 &&
+ doRoundRobin == 0)
+ {
+ if (nxagentCorruptedBackgrounds > 0)
+ {
+ fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] "
+ "corrupted backgrounds.\n", nxagentCorruptedBackgrounds);
+ }
+
+ nxagentCorruptedBackgrounds = 0;
+ }
+
+ #endif
+ }
+
+ /*
+ * If there is bandwidth remaining, synchronize
+ * the pixmaps. Synchronizing a pixmap doesn't
+ * produce any visible results. Better is to
+ * synchronize them on demand, before using the
+ * pixmap in a copy or in a composite operation.
+ */
+
+ if (nxagentSynchronization.abort == 0 &&
+ NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_PIXMAPS(mask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Going to loop through corrupted pixmap resources.\n");
+ #endif
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_PIXMAP,
+ nxagentSynchronizeDrawablePredicate, &breakMask);
+
+
+ if (nxagentSynchronization.abort == 0 &&
+ nxagentSynchronization.pixmapBitmaps == 0 &&
+ doRoundRobin == 0)
+ {
+ #ifdef TEST
+
+ if (nxagentCorruptedPixmaps > 0)
+ {
+ fprintf(stderr, "nxagentSynchronizationLoop: Closing the loop with [%d] "
+ "corrupted pixmaps.\n", nxagentCorruptedPixmaps);
+ }
+
+ #endif
+
+ nxagentCorruptedPixmaps = 0;
+ }
+
+ }
+
+ /*
+ * If the last synchronized drawable has been
+ * removed, we have to reset the variable sto-
+ * ring its pointer.
+ */
+
+ if (nxagentSynchronization.pDrawable != NULL &&
+ nxagentFindClientResource(serverClient -> index, RT_NX_CORR_WINDOW,
+ nxagentSynchronization.pDrawable) == 0 &&
+ nxagentFindClientResource(serverClient -> index, RT_NX_CORR_BACKGROUND,
+ nxagentSynchronization.pDrawable) == 0 &&
+ nxagentFindClientResource(serverClient -> index, RT_NX_CORR_PIXMAP,
+ nxagentSynchronization.pDrawable) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Synchronization drawable [%p] removed from resources.\n",
+ (void *) nxagentSynchronization.pDrawable);
+ #endif
+
+ nxagentSynchronization.pDrawable = NULL;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizationLoop: Closing loops with congestion [%d] "
+ "blocking [%d].\n", nxagentCongestion, nxagentBlocking);
+
+ fprintf(stderr, "nxagentSynchronizationLoop: There are now [%d] windows [%d] pixmaps "
+ "and [%d] backgrounds to synchronize.\n", nxagentCorruptedWindows,
+ nxagentCorruptedPixmaps, nxagentCorruptedBackgrounds);
+ #endif
+}
+
+RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int width, int height)
+{
+ RegionPtr pRegion;
+ BoxRec box;
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = x + width;
+ box.y2 = y + height;
+
+ pRegion = RegionCreate(&box, 1);
+
+ /*
+ * Clipping the region.
+ */
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ BoxRec tmpBox;
+ RegionRec tmpRegion;
+
+ /*
+ * The region created doesn't need to be clipped
+ * if it has the pixmap dimensions.
+ */
+
+ if (x != 0 || y != 0 ||
+ width != pDrawable -> width ||
+ height != pDrawable -> height)
+ {
+ tmpBox.x1 = 0;
+ tmpBox.y1 = 0;
+ tmpBox.x2 = pDrawable -> width;
+ tmpBox.y2 = pDrawable -> height;
+
+ RegionInit(&tmpRegion, &tmpBox, 1);
+
+ RegionIntersect(pRegion, &tmpRegion, pRegion);
+
+ RegionUninit(&tmpRegion);
+ }
+ }
+ else
+ {
+ /*
+ * We use the clipList because the borderClip
+ * contains also parts of the window covered
+ * by its children.
+ */
+
+ RegionTranslate(pRegion,
+ pDrawable -> x, pDrawable -> y);
+
+ if (nxagentWindowPriv((WindowPtr) pDrawable) -> hasTransparentChildren == 1)
+ {
+ RegionIntersect(pRegion, pRegion, &((WindowPtr) pDrawable) -> borderClip);
+ }
+ else
+ {
+ RegionIntersect(pRegion, pRegion, &((WindowPtr) pDrawable) -> clipList);
+ }
+
+ RegionTranslate(pRegion,
+ -pDrawable -> x, -pDrawable -> y);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateRegion: New region created with coordinates [%d,%d,%d,%d].\n",
+ pRegion -> extents.x1, pRegion -> extents.y1,
+ pRegion -> extents.x2, pRegion -> extents.y2);
+ #endif
+
+ /*
+ * If the pRegion is NIL we don't need
+ * to intersect it with the GC's clipmask.
+ */
+
+ if (RegionNil(pRegion) == 0 &&
+ pGC != NULL && pGC -> clientClip != NULL &&
+ pGC -> clientClipType == CT_REGION)
+ {
+ RegionRec clipRegion;
+
+ RegionInit(&clipRegion, NullBox, 1);
+
+ RegionCopy(&clipRegion, (RegionPtr) pGC -> clientClip);
+
+ /*
+ * The clip origin is relative to the origin of
+ * the destination drawable. The clip mask coor-
+ * dinates are relative to the clip origin.
+ */
+
+ if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0)
+ {
+ RegionTranslate(&clipRegion, pGC -> clipOrg.x, pGC -> clipOrg.y);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateRegion: Clipping region to the clip mask with coordinates [%d,%d,%d,%d].\n",
+ clipRegion.extents.x1, clipRegion.extents.y1,
+ clipRegion.extents.x2, clipRegion.extents.y2);
+ #endif
+
+ RegionIntersect(pRegion, pRegion, &clipRegion);
+
+ RegionUninit(&clipRegion);
+ }
+
+ return pRegion;
+}
+
+void nxagentMarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ int x;
+ int y;
+ int width;
+ int height;
+
+ if (pRegion != NullRegion && RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMarkCorruptedRegion: Region [%d,%d,%d,%d] is nil. Skipping operation.\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2);
+ #endif
+
+ return;
+ }
+
+ /*
+ * If the drawable was synchronized, the counter
+ * reporting the number of corrupted drawables
+ * must be increased. Moreover the corrupted ti-
+ * mestamp must be set.
+ */
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ if (pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ nxagentAllocateCorruptedResource(pDrawable, RT_NX_CORR_WINDOW);
+ }
+
+ nxagentSetCorruptedTimestamp(pDrawable);
+ }
+
+ if (pRegion == NullRegion)
+ {
+ x = 0;
+ y = 0;
+
+ width = pDrawable -> width;
+ height = pDrawable -> height;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentMarkCorruptedRegion: Fully invalidating %s [%p] with "
+ "coordinates [%d,%d][%d,%d].\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, x, y, width, height);
+ #endif
+
+ pRegion = nxagentCreateRegion(pDrawable, NULL, x, y, width, height);
+
+ nxagentValidateSplit(pDrawable, pRegion);
+
+ RegionUnion(nxagentCorruptedRegion(pDrawable),
+ nxagentCorruptedRegion(pDrawable), pRegion);
+
+ nxagentFreeRegion(pDrawable, pRegion);
+ }
+ else
+ {
+ #ifdef TEST
+
+ x = pRegion -> extents.x1;
+ y = pRegion -> extents.y1;
+
+ width = pRegion -> extents.x2 - pRegion -> extents.x1;
+ height = pRegion -> extents.y2 - pRegion -> extents.y1;
+
+ fprintf(stderr, "nxagentMarkCorruptedRegion: Partly invalidating %s [%p] with "
+ "coordinates [%d,%d][%d,%d].\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable, x, y, width, height);
+
+ #endif
+
+ nxagentValidateSplit(pDrawable, pRegion);
+
+ RegionUnion(nxagentCorruptedRegion(pDrawable),
+ nxagentCorruptedRegion(pDrawable), pRegion);
+ }
+}
+
+void nxagentUnmarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ int oldStatus;
+
+ if (pRegion != NullRegion && RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentUnmarkCorruptedRegion: Region [%d,%d,%d,%d] is nil. Skipping operation.\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2);
+ #endif
+
+ return;
+ }
+
+ oldStatus = nxagentDrawableStatus(pDrawable);
+
+ if (oldStatus == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentUnmarkCorruptedRegion: Drawable %s [%p] already synchronized.\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ if (pRegion == NullRegion)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentUnmarkCorruptedRegion: Fully validating %s [%p].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ nxagentValidateSplit(pDrawable, NULL);
+
+ RegionEmpty(nxagentCorruptedRegion(pDrawable));
+ }
+ else
+ {
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentUnmarkCorruptedRegion: Validating %s [%p] with region [%d,%d,%d,%d].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable,
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2);
+
+ #endif
+
+ nxagentValidateSplit(pDrawable, pRegion);
+
+ RegionSubtract(nxagentCorruptedRegion(pDrawable),
+ nxagentCorruptedRegion(pDrawable), pRegion);
+ }
+
+ /*
+ * If the drawable becomes synchronized, the
+ * counter reporting the number of corrupted
+ * drawables must be decreased. Moreover the
+ * corrupted timestamp must be reset.
+ */
+
+ if (oldStatus == NotSynchronized &&
+ nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_BACKGROUND);
+
+ nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_PIXMAP);
+
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> containTrapezoids = 0;
+ }
+ else
+ {
+ nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_WINDOW);
+ }
+
+ nxagentResetCorruptedTimestamp(pDrawable);
+
+ /*
+ * If the resource is no longer dirty,
+ * the associated bitmap is destroyed.
+ */
+
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ nxagentDestroyDrawableBitmap(pDrawable);
+ }
+ }
+}
+
+void nxagentMoveCorruptedRegion(WindowPtr pWin, unsigned int mask)
+{
+ /*
+ * If a window is resized, its corrupted
+ * region is moved according to the bit
+ * gravity.
+ */
+
+ if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
+ {
+ if (((mask & CWHeight) && nxagentWindowPriv(pWin) -> height != pWin -> drawable.height) ||
+ ((mask & CWWidth) && nxagentWindowPriv(pWin) -> width != pWin -> drawable.width))
+ {
+ int nx, ny;
+
+ GravityTranslate(0, 0,
+ nxagentWindowPriv(pWin) -> x - pWin -> origin.x + wBorderWidth(pWin),
+ nxagentWindowPriv(pWin) -> y - pWin -> origin.y + wBorderWidth(pWin),
+ pWin -> drawable.width - nxagentWindowPriv(pWin) -> width,
+ pWin -> drawable.height - nxagentWindowPriv(pWin) -> height,
+ pWin -> bitGravity, &nx, &ny);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentMoveCorruptedRegion: Moving the corrupted region to [%d,%d] for window [%p].\n",
+ nx, ny, (void *) pWin);
+ #endif
+
+ RegionTranslate(nxagentCorruptedRegion((DrawablePtr) pWin),
+ nx, ny);
+
+ /*
+ * Having moved the corrupted region, we
+ * need to invalidate the pending commits
+ * or otherwise the image will fall in
+ * the wrong area.
+ */
+
+ nxagentValidateSplit((DrawablePtr) pWin, NULL);
+
+
+ /*
+ * The window reconfiguration invalidates
+ * the synchronization bitmap.
+ */
+
+ nxagentDestroyDrawableBitmap((DrawablePtr) pWin);
+ }
+ }
+}
+
+/*
+ * The DDX layer uses an 'Y-X banding' representation of
+ * regions: it sorts all rectangles composing a region
+ * using first the y-dimension, than the x-dimension; mo-
+ * reover it organizes the rectangles in 'bands' sharing
+ * the same y-dimension. This representation does not mi-
+ * nimize the number of rectangles. For example, the fol-
+ * lowing region has 4 rectangles:
+ *
+ * +-----------+
+ * | | +---+
+ * | A | | B |
+ * | | +---+
+ * +-----------+
+ *
+ * The rectangle 'B' creates a band which splits the rec-
+ * tangle A in 3 parts, for a total of 3 bands. The num-
+ * ber of rectangles composing the region is 4.
+ *
+ * This kind of representation is not advisable for the
+ * lazy synchronization because, in the example above,
+ * the nxagent had to send 4 put images instead of 2.
+ *
+ * To minimize the problem we use the following function:
+ * by traversing the list of rectangles we merge all bo-
+ * xes with same x coordinates and coincident y, in order
+ * to create an X-Y banding.
+ *
+ * Be careful: all the coordinates of boxes merged are
+ * set to 0, so take care of this when looping through
+ * the box list returned by this function.
+ */
+
+BoxPtr nxagentGetOptimizedRegionBoxes(RegionPtr pRegion)
+{
+ BoxPtr pBox;
+
+ BoxRec boxExtents;
+
+ int nBox;
+ int i, j;
+
+ #ifdef DEBUG
+ int nBoxOptim;
+ #endif
+
+ pBox = RegionRects(pRegion);
+
+ nBox = RegionNumRects(pRegion);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to optimize region at [%p] with [%d] rects.\n",
+ (void *) pRegion, nBox);
+ #endif
+
+ if (nBox <= 1)
+ {
+ return pBox;
+ }
+
+ #ifdef DEBUG
+ nBoxOptim = nBox;
+ #endif
+
+ /*
+ * The boxes are now grouped to grown as much
+ * as possible, using their overlapping vertex
+ * as rule.
+ */
+
+ for (i = 0; i < nBox; i++)
+ {
+ /*
+ * If the coordinates are (0,0) the box
+ * has been already merged, so we can skip
+ * it.
+ */
+
+ if (pBox[i].x1 == 0 && pBox[i].y1 == 0 &&
+ pBox[i].x2 == 0 && pBox[i].y2 == 0)
+ {
+ continue;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Referential box [%d] has coordinates [%d,%d,%d,%d].\n",
+ i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2);
+ #endif
+
+ #ifdef ADVANCED_BOXES_DEFRAG
+
+ boxExtents.x1 = pBox[i].x1;
+ boxExtents.y1 = pBox[i].y1;
+ boxExtents.x2 = pBox[i].x2;
+
+ #endif
+
+ boxExtents.y2 = pBox[i].y2;
+
+ for (j = i+1; j < nBox; j++)
+ {
+ if (pBox[j].x1 == 0 && pBox[j].y1 == 0 &&
+ pBox[j].x2 == 0 && pBox[j].y2 == 0)
+ {
+ continue;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Mergeable box [%d] has coordinates [%d,%d,%d,%d].\n",
+ j, pBox[j].x1, pBox[j].y1, pBox[j].x2, pBox[j].y2);
+ #endif
+
+ /*
+ * Each consequent box is merged if its
+ * higher side overlaps the lower side
+ * of current box.
+ * In case of ADVANCED_BOXES_DEFRAG the higher
+ * side must be included within a range
+ * defined by INCLUDE_MARGIN.
+ */
+
+ #ifndef ADVANCED_BOXES_DEFRAG
+
+ if (pBox[j].y1 == boxExtents.y2 &&
+ pBox[j].x1 == pBox[i].x1 &&
+ pBox[j].x2 == pBox[i].x2)
+
+ #else
+
+ if (pBox[j].x1 > boxExtents.x1 - INCLUDE_MARGIN &&
+ pBox[j].x1 < boxExtents.x1 + INCLUDE_MARGIN &&
+ pBox[j].y1 > boxExtents.y2 - INCLUDE_MARGIN &&
+ pBox[j].y1 < boxExtents.y2 + INCLUDE_MARGIN &&
+ pBox[j].x2 > boxExtents.x2 - INCLUDE_MARGIN &&
+ pBox[j].x2 < boxExtents.x2 + INCLUDE_MARGIN)
+
+ #endif
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to merge box at [%d] with box at [%d].\n",
+ j, i);
+ #endif
+
+ #ifdef ADVANCED_BOXES_DEFRAG
+
+ if (pBox[j].x1 < boxExtents.x1)
+ {
+ boxExtents.x1 = pBox[j].x1;
+ }
+
+ if (pBox[j].x2 > boxExtents.x2)
+ {
+ boxExtents.x2 = pBox[j].x2;
+ }
+
+ if (pBox[j].y1 < boxExtents.y1)
+ {
+ boxExtents.y1 = pBox[j].y1;
+ }
+
+ #endif
+
+ if (pBox[j].y2 > boxExtents.y2)
+ {
+ boxExtents.y2 = pBox[j].y2;
+ }
+
+ /*
+ * By appending a box to another, we have
+ * to remove it from the box list. We do
+ * this by setting its coordinates to (0,0)
+ * and by checking their value in the main
+ * loop.
+ */
+
+ pBox[j].x1 = pBox[j].y1 = pBox[j].x2 = pBox[j].y2 = 0;
+
+ #ifdef DEBUG
+ nBoxOptim--;
+ #endif
+ }
+ }
+
+ /*
+ * Extend the box height.
+ */
+
+ #ifdef ADVANCED_BOXES_DEFRAG
+
+ pBox[i].x1 = boxExtents.x1;
+ pBox[i].y1 = boxExtents.y1;
+ pBox[i].x2 = boxExtents.x2;
+
+ #endif
+
+ pBox[i].y2 = boxExtents.y2;
+ }
+
+ #ifdef ADVANCED_BOXES_DEFRAG
+
+ /*
+ * The new list need to be validated to
+ * avoid boxes overlapping. This code may
+ * be improved to remove also the partial-
+ * ly overlapping boxes.
+ */
+
+ for (i = 0; i < nBox; i++)
+ {
+ if (pBox[i].x1 == 0 && pBox[i].y1 == 0 &&
+ pBox[i].x2 == 0 && pBox[i].y2 == 0)
+ {
+ continue;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Referential box [%d] has coordinates [%d,%d,%d,%d].\n",
+ i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2);
+ #endif
+
+ boxExtents.x1 = pBox[i].x1;
+ boxExtents.y1 = pBox[i].y1;
+ boxExtents.x2 = pBox[i].x2;
+ boxExtents.y2 = pBox[i].y2;
+
+ for (j = i+1; j < nBox; j++)
+ {
+ if (pBox[j].x1 == 0 && pBox[j].y1 == 0 &&
+ pBox[j].x2 == 0 && pBox[j].y2 == 0)
+ {
+ continue;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Mergeable box [%d] has coordinates [%d,%d,%d,%d].\n",
+ j, pBox[j].x1, pBox[j].y1, pBox[j].x2, pBox[j].y2);
+ #endif
+
+ if ((boxExtents.x1 <= pBox[j].x1 &&
+ boxExtents.x2 >= pBox[j].x2 &&
+ boxExtents.y1 <= pBox[j].y1 &&
+ boxExtents.y2 >= pBox[j].y2))
+ {
+ /*
+ * If a box is completely inside
+ * another, we set its coordinates
+ * to 0 to consider it as merged.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Going to merge box [%d,%d,%d,%d] "
+ "with its box container [%d,%d,%d,%d].\n", pBox[j].x1, pBox[j].y1,
+ pBox[j].x2, pBox[j].y2, boxExtents.x1, boxExtents.y1, boxExtents.y1,
+ boxExtents.y2);
+ #endif
+
+ pBox[j].x1 = pBox[j].y1 = pBox[j].x2 = pBox[j].y2 = 0;
+
+ #ifdef DEBUG
+ nBoxOptim--;
+ #endif
+ }
+ }
+ }
+
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetOptimizedRegionBoxes: Original boxes number [%d] Optimized boxes number [%d].\n",
+ nBox, nBoxOptim);
+ #endif
+
+ return pBox;
+}
+
+unsigned long nxagentGetColor(DrawablePtr pDrawable, int xPixel, int yPixel)
+{
+ XImage *ximage;
+ Visual *pVisual;
+ char *data;
+
+ int depth, format, length;
+ int leftPad = 0;
+ unsigned long pixel;
+
+ depth = pDrawable -> depth;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+ length = nxagentImageLength(1, 1, format, leftPad, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGetColor: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ return -1;
+ }
+
+ pVisual = nxagentImageVisual(pDrawable, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGetColor: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ fbGetImage(pDrawable, xPixel, yPixel, 1, 1, format, AllPlanes, data);
+
+ ximage = XCreateImage(nxagentDisplay, pVisual, depth, format, leftPad, (char *) data,
+ 1, 1, BitmapPad(nxagentDisplay),
+ nxagentImagePad(1, format, leftPad, 1));
+
+ if (ximage == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGetColor: WARNING! Failed to create the XImage.\n");
+ #endif
+
+ free(data);
+
+ return -1;
+ }
+
+ pixel = XGetPixel(ximage, 0, 0);
+
+ XDestroyImage(ximage);
+
+ return pixel;
+}
+
+/*
+ * This function could be used to determine
+ * the ClearArea color of corrupted regions
+ * on screen.
+ */
+
+unsigned long nxagentGetRegionColor(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ int xPicker, yPicker;
+
+ if (RegionNil(pRegion) == 1)
+ {
+ return nxagentGetDrawableColor(pDrawable);
+ }
+
+ /*
+ * The pixel used as reference is the first
+ * outer pixel at the bottom right corner
+ * of corrupted region extents.
+ */
+
+ xPicker = pRegion -> extents.x2 + 1;
+
+ if (xPicker > pDrawable -> width)
+ {
+ xPicker = pDrawable -> width;
+ }
+
+ yPicker = pRegion -> extents.y2 + 1;
+
+ if (yPicker > pDrawable -> height)
+ {
+ yPicker = pDrawable -> height;
+ }
+
+ return nxagentGetColor(pDrawable, xPicker, yPicker);
+}
+
+unsigned long nxagentGetDrawableColor(DrawablePtr pDrawable)
+{
+ int xPicker, yPicker;
+
+ /*
+ * The pixel used to determine the co-
+ * lor of a drawable is at coordinates
+ * (x + width - 4, y + 4).
+ */
+
+ xPicker = pDrawable -> width - 4;
+
+ yPicker = 4;
+
+ return nxagentGetColor(pDrawable, xPicker, yPicker);
+}
+
+void nxagentClearRegion(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ WindowPtr pWin;
+ BoxPtr pBox;
+
+ unsigned long color;
+ unsigned long backupPixel = 0;
+ int nBox, i;
+ int restore;
+
+ #ifdef DEBUG
+ static int nBoxCleared;
+ #endif
+
+ if (pDrawable -> type != DRAWABLE_WINDOW)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentClearRegion: Cannot clear a pixmap. Exiting.\n");
+ #endif
+
+ return;
+ }
+
+ if (pRegion == NullRegion || RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentClearRegion: The region is empty. Exiting.\n");
+ #endif
+
+ return;
+ }
+
+ pWin = (WindowPtr) pDrawable;
+
+ restore = 0;
+
+ /*
+ * If the window has already a background, we
+ * can hope it will be nice.
+ */
+
+ if (pWin -> backgroundState != None)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearRegion: Window at [%p] has background state [%u].\n",
+ (void *) pWin, pWin -> backgroundState);
+ #endif
+ }
+ else
+ {
+ /*
+ * Save the original state.
+ */
+
+ backupPixel = pWin -> background.pixel;
+
+ color = nxagentGetDrawableColor((DrawablePtr) pWin);
+
+ if (color == -1)
+ {
+ color = 0xffffff;
+ }
+
+ pWin -> backgroundState = BackgroundPixel;
+ pWin -> background.pixel = color;
+
+ nxagentChangeWindowAttributes(pWin, CWBackPixel);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearRegion: Window at [%p] now has pixel background [%ld].\n",
+ (void *) pWin, color);
+ #endif
+
+ restore = 1;
+ }
+
+ pBox = nxagentGetOptimizedRegionBoxes(pRegion);
+
+ nBox = RegionNumRects(pRegion);
+
+ for (i = 0; i < nBox; i++)
+ {
+ if (pBox[i].x1 == 0 && pBox[i].y1 == 0 &&
+ pBox[i].x2 == 0 && pBox[i].y2 == 0)
+ {
+ continue;
+ }
+
+ XClearArea(nxagentDisplay, nxagentWindow(pWin), pBox[i].x1, pBox[i].y1,
+ pBox[i].x2 - pBox[i].x1, pBox[i].y2 - pBox[i].y1, False);
+
+ #ifdef DEBUG
+ nBoxCleared++;
+ #endif
+ }
+
+ /*
+ * Restore the old state.
+ */
+
+ if (restore == 1)
+ {
+ pWin -> backgroundState = None;
+ pWin -> background.pixel = backupPixel;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClearRegion: Number of cleared boxes is [%d].\n", nBoxCleared);
+ #endif
+}
+
+void nxagentFillRemoteRegion(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ GCPtr pGC;
+ BoxPtr pBox;
+ XRectangle *pRects;
+
+ int nrects;
+ int i;
+
+ if (RegionNil(pRegion) == 1)
+ {
+ return;
+ }
+
+ pGC = nxagentGetGraphicContext(pDrawable);
+
+ nrects = RegionNumRects(pRegion);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFillRemoteRegion: Going to fill remote region [%d,%d,%d,%d] rects [%d] with color [%lu].\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2,
+ nrects, pGC -> fgPixel);
+ #endif
+
+ if (nrects == 1)
+ {
+ XFillRectangle(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ pRegion -> extents.x1, pRegion -> extents.y1,
+ pRegion -> extents.x2 - pRegion -> extents.x1,
+ pRegion -> extents.y2 - pRegion -> extents.y1);
+ }
+ else
+ {
+ pBox = RegionRects(pRegion);
+
+ pRects = malloc(nrects * sizeof(XRectangle));
+
+ for (i = 0; i < nrects; i++)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ pRects, nrects);
+
+ free(pRects);
+ }
+}
+
+int nxagentDestroyCorruptedWindowResource(void * p, XID id)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedWindowResource: Removing corrupted window [%p] from resources.\n",
+ (void *) p);
+ #endif
+
+ nxagentWindowPriv((WindowPtr) p) -> corruptedId = None;
+
+ return 1;
+}
+
+int nxagentDestroyCorruptedPixmapResource(void * p, XID id)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedPixmapResource: Removing corrupted pixmap [%p] from resources.\n",
+ (void *) p);
+ #endif
+
+ nxagentPixmapPriv((PixmapPtr) p) -> corruptedId = None;
+
+ return 1;
+}
+
+int nxagentDestroyCorruptedBackgroundResource(void * p, XID id)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedBackgroundResource: Removing corrupted pixmap background [%p] from resources.\n",
+ (void *) p);
+ #endif
+
+ nxagentPixmapPriv((PixmapPtr) p) -> corruptedBackgroundId = None;
+
+ return 1;
+}
+
+void nxagentPointsToDirtyRegion(DrawablePtr pDrawable, int mode,
+ int nPoints, xPoint *pPoints)
+{
+ RegionPtr pRegion;
+ RegionRec tmpRegion;
+ BoxRec box, extents;
+
+ xPoint *xp;
+ int np;
+
+ np = nPoints;
+ xp = pPoints;
+
+ pRegion = RegionCreate(NullBox, 1);
+
+ while (np--)
+ {
+ if (CoordModePrevious)
+ {
+ box.x1 = box.x2 = (xp-1) -> x + xp -> x;
+ box.y1 = box.y2 = (xp-1) -> y + xp -> y;
+ }
+ else
+ {
+ box.x1 = box.x2 = xp -> x;
+ box.y1 = box.y2 = xp -> y;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointsToDirtyRegion: Adding the point (%d,%d) to the dirty region.\n",
+ box.x1, box.y1);
+ #endif
+
+ /*
+ * By using REGION_APPEND() and REGION_VALIDATE()
+ * this loop could become less expensive.
+ */
+
+ RegionInit(&tmpRegion, &box, 1);
+
+ RegionUnion(pRegion, pRegion, &tmpRegion);
+
+ RegionUninit(&tmpRegion);
+
+ xp++;
+ }
+
+ extents = *RegionExtents(pRegion);
+
+ RegionReset(pRegion, &extents);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointsToDirtyRegion: The resulting dirty region has [%ld] rects and"
+ " extents (%d,%d,%d,%d).\n", RegionNumRects(pRegion), extents.x1,
+ extents.y1, extents.x2, extents.y2);
+ #endif
+
+ nxagentMarkCorruptedRegion(pDrawable, pRegion);
+
+ RegionDestroy(pRegion);
+}
+
+#ifdef DUMP
+
+#define USE_MULTIPLE_COLORS
+
+void nxagentCorruptedRegionOnWindow(void *p0, XID x, void *p2)
+{
+ WindowPtr pWin = (WindowPtr) p0;
+ RegionPtr clipRegion;
+ RegionRec visRegion;
+ BoxPtr pBox;
+
+ XlibGC gc;
+ XGCValues value;
+
+ static unsigned long color = 0xff000000;
+ int nrectangles;
+ int i;
+
+ /*
+ * There are no regions to draw.
+ */
+
+ if (nxagentDrawableStatus((DrawablePtr) pWin) == Synchronized)
+ {
+ return;
+ }
+
+ /*
+ * The window is not visible.
+ */
+
+ if (nxagentWindowIsVisible(pWin) == 0)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorruptedRegionOnWindow: Going to draw on window at [%p].\n",
+ (void *) pWin);
+ #endif
+
+ clipRegion = nxagentCreateRegion((DrawablePtr) pWin, NULL, 0, 0,
+ pWin -> drawable.width, pWin -> drawable.height);
+
+ RegionInit(&visRegion, NullBox, 1);
+
+ RegionIntersect(&visRegion, clipRegion, nxagentCorruptedRegion((DrawablePtr) pWin));
+
+ nxagentFreeRegion(pWin -> drawable.pScreen, clipRegion);
+
+ if (RegionNil(&visRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorruptedRegionOnWindow: The corrupted region of window at [%p] is hidden.\n",
+ (void *) pWin);
+ #endif
+
+ RegionUninit(&visRegion);
+
+ return;
+ }
+
+ nxagentClearRegion((DrawablePtr) pWin, &visRegion);
+
+ #ifdef USE_MULTIPLE_COLORS
+
+ color += nxagentWindow(pWin) * 5;
+
+ if (color == 0 || color == 0xffffffff)
+ {
+ color = 0xff000000;
+ }
+
+ #endif
+
+ value.foreground = color;
+ value.subwindow_mode = IncludeInferiors;
+
+ gc = XCreateGC(nxagentDisplay, nxagentWindow(pWin), GCForeground | GCSubwindowMode, &value);
+
+ nrectangles = RegionNumRects(&visRegion);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorruptedRegionOnWindow: Going to draw the region with extents [%d,%d,%d,%d] and [%d] rects.\n",
+ visRegion.extents.x1, visRegion.extents.y1, visRegion.extents.x2, visRegion.extents.y2,
+ nrectangles);
+ #endif
+
+ pBox = nxagentGetOptimizedRegionBoxes(&visRegion);
+
+ for (i = 0; i < nrectangles; i++)
+ {
+ if (pBox[i].x1 == 0 && pBox[i].y1 == 0 &&
+ pBox[i].x2 == 0 && pBox[i].y2 == 0)
+ {
+ continue;
+ }
+
+ XDrawRectangle(nxagentDisplay, nxagentWindow(pWin), gc,
+ pBox[i].x1, pBox[i].y1, pBox[i].x2 - pBox[i].x1 - 1,
+ pBox[i].y2 - pBox[i].y1 - 1);
+ }
+
+ XFreeGC(nxagentDisplay, gc);
+
+ RegionUninit(&visRegion);
+}
+
+void nxagentRegionsOnScreen()
+{
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_CORR_WINDOW,
+ nxagentCorruptedRegionOnWindow, NULL);
+}
+
+#endif
+
+/*
+ * If the synchronization loop breaks and the
+ * drawable synchronization cannot be completed,
+ * the remaining data is stored in a bitmap.
+ * The synchronization loop is then restarted
+ * using the bitmap as source instead of the
+ * drawable.
+ */
+
+void nxagentCreateDrawableBitmap(DrawablePtr pDrawable)
+{
+ PixmapPtr pBitmap;
+ GCPtr pGC = NULL;
+ RegionPtr pClipRegion = NullRegion;
+
+ int x, y;
+ int w, h;
+ int saveTrap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateDrawableBitmap: Creating synchronization bitmap for [%s] at [%p].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ /*
+ * The bitmap is created only in the
+ * nxagent.
+ */
+
+ saveTrap = nxagentGCTrap;
+
+ nxagentGCTrap = 1;
+
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateDrawableBitmap: The drawable is already synchronized. Skipping bitmap creation.\n");
+ #endif
+
+ goto nxagentCreateDrawableBitmapEnd;
+ }
+
+ /*
+ * Should create a function to append
+ * a bitmap to another, instead of de-
+ * stroy the old one.
+ */
+
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateDrawableBitmap: WARNING! Going to replace the bitmap at [%p] with corrupted [%d,%d,%d,%d].\n",
+ (void *) nxagentDrawableBitmap(pDrawable),
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2);
+ #endif
+
+ nxagentDestroyDrawableBitmap(pDrawable);
+ }
+
+ /*
+ * Clipping to the visible area.
+ */
+
+ pClipRegion = nxagentCreateRegion(pDrawable, NULL, 0, 0, pDrawable -> width, pDrawable -> height);
+
+ RegionIntersect(pClipRegion, pClipRegion, nxagentCorruptedRegion(pDrawable));
+
+ if (RegionNil(pClipRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateDrawableBitmap: The corrupted region is not visible. Skipping bitmap creation.\n");
+ #endif
+
+ goto nxagentCreateDrawableBitmapEnd;
+ }
+
+ /*
+ * FIXME: A better way it would be create the bitmap
+ * with the same extents of the clipRegion. This
+ * requires to save the offset with respect to the
+ * drawable origin like in the backing store. This
+ * becomes particularly important when the drawable
+ * is a huge window, because the pixmap creation
+ * would fail.
+ */
+
+ pBitmap = nxagentCreatePixmap(pDrawable -> pScreen, pDrawable -> width, pDrawable -> height, pDrawable -> depth, 0);
+
+ if (pBitmap == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateDrawableBitmap: Cannot create pixmap for the bitmap data.\n");
+ #endif
+
+ goto nxagentCreateDrawableBitmapEnd;
+ }
+
+ pGC = GetScratchGC(pBitmap -> drawable.depth, pBitmap -> drawable.pScreen);
+
+ ValidateGC((DrawablePtr) pBitmap, pGC);
+
+ x = pClipRegion -> extents.x1;
+ y = pClipRegion -> extents.y1;
+ w = pClipRegion -> extents.x2 - pClipRegion -> extents.x1;
+ h = pClipRegion -> extents.y2 - pClipRegion -> extents.y1;
+
+ nxagentCopyArea(pDrawable, (DrawablePtr) pBitmap, pGC, x, y, w, h, x, y);
+
+ RegionUnion(nxagentCorruptedRegion((DrawablePtr) pBitmap),
+ nxagentCorruptedRegion((DrawablePtr) pBitmap), pClipRegion);
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> synchronizationBitmap = pBitmap;
+
+ if (nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1)
+ {
+ nxagentSynchronization.backgroundBitmaps++;
+ }
+ else
+ {
+ nxagentSynchronization.pixmapBitmaps++;
+ }
+ }
+ else
+ {
+ nxagentWindowPriv((WindowPtr) pDrawable) -> synchronizationBitmap = pBitmap;
+
+ nxagentSynchronization.windowBitmaps++;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateDrawableBitmap: Drawable [%p] has bitmap at [%p] with corrupted [%d,%d,%d,%d].\n",
+ (void *) pDrawable, (void *) nxagentDrawableBitmap(pDrawable),
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y1,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.x2,
+ nxagentCorruptedRegion((DrawablePtr) nxagentDrawableBitmap(pDrawable)) -> extents.y2);
+ #endif
+
+nxagentCreateDrawableBitmapEnd:
+
+ nxagentGCTrap = saveTrap;
+
+ if (pClipRegion != NullRegion)
+ {
+ nxagentFreeRegion(pDrawable, pClipRegion);
+ }
+
+ if (pGC != NULL)
+ {
+ FreeScratchGC(pGC);
+ }
+}
+
+void nxagentDestroyDrawableBitmap(DrawablePtr pDrawable)
+{
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyDrawableBitmap: Destroying bitmap for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ nxagentDestroyPixmap(nxagentDrawableBitmap(pDrawable));
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> synchronizationBitmap = NullPixmap;
+
+ if (nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1)
+ {
+ nxagentSynchronization.backgroundBitmaps--;
+ }
+ else
+ {
+ nxagentSynchronization.pixmapBitmaps--;
+ }
+ }
+ else
+ {
+ nxagentWindowPriv((WindowPtr) pDrawable) -> synchronizationBitmap = NullPixmap;
+
+ nxagentSynchronization.windowBitmaps--;
+ }
+ }
+}
+
+void nxagentIncreasePixmapUsageCounter(PixmapPtr pPixmap)
+{
+ if (nxagentDrawableStatus((DrawablePtr) pPixmap) == Synchronized)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentIncreasePixmapUsageCounter: Pixmap usage counter was [%d].\n",
+ nxagentPixmapUsageCounter(pPixmap));
+ #endif
+
+ nxagentPixmapUsageCounter(pPixmap) += 1;
+
+ nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP);
+}
+
+void nxagentAllocateCorruptedResource(DrawablePtr pDrawable, RESTYPE type)
+{
+ PixmapPtr pRealPixmap;
+
+ if (nxagentSessionState == SESSION_DOWN)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAllocateCorruptedResource: WARNING! Not allocated corrupted resource "
+ "[%s][%p] with the display down.\n", nxagentDrawableType(pDrawable),
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ if (type == RT_NX_CORR_WINDOW)
+ {
+ if (nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted "
+ "windows counter was [%d].\n", (void *) pDrawable, nxagentCorruptedWindows);
+ #endif
+
+ nxagentCorruptedWindows++;
+
+ nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId = FakeClientID(serverClient -> index);
+
+ AddResource(nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId, RT_NX_CORR_WINDOW,
+ (void *) pDrawable);
+ }
+ }
+ else if (type == RT_NX_CORR_BACKGROUND)
+ {
+ pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable);
+
+ if (nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId == 0)
+ {
+ /*
+ * When a pixmap is added to the background
+ * corrupted resources, it must be removed
+ * from the pixmap corrupted resources.
+ */
+
+ nxagentDestroyCorruptedResource(pDrawable, RT_NX_CORR_PIXMAP);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted "
+ "backgrounds counter was [%d].\n", (void *) pDrawable, nxagentCorruptedBackgrounds);
+ #endif
+
+ nxagentCorruptedBackgrounds++;
+
+ nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId = FakeClientID(serverClient -> index);
+
+ AddResource(nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId, RT_NX_CORR_BACKGROUND,
+ (void *) pRealPixmap);
+ }
+ }
+ else if (type == RT_NX_CORR_PIXMAP)
+ {
+ /*
+ * The shared memory pixmaps are always dirty
+ * and shouldn't be synchronized.
+ */
+
+ if (nxagentPixmapUsageCounter((PixmapPtr) pDrawable) >= MINIMUM_PIXMAP_USAGE_COUNTER &&
+ nxagentIsShmPixmap((PixmapPtr) pDrawable) == 0)
+ {
+ pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable);
+
+ if (nxagentPixmapPriv(pRealPixmap) -> corruptedId == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAllocateCorruptedResource: New resource at [%p]. Corrupted "
+ "pixmaps counter was [%d].\n", (void *) pDrawable, nxagentCorruptedPixmaps);
+ #endif
+
+ nxagentCorruptedPixmaps++;
+
+ nxagentPixmapPriv(pRealPixmap) -> corruptedId = FakeClientID(serverClient -> index);
+
+ AddResource(nxagentPixmapPriv(pRealPixmap) -> corruptedId, RT_NX_CORR_PIXMAP,
+ (void *) pRealPixmap);
+ }
+ }
+ }
+}
+
+void nxagentDestroyCorruptedResource(DrawablePtr pDrawable, RESTYPE type)
+{
+ PixmapPtr pRealPixmap;
+
+ if (type == RT_NX_CORR_WINDOW)
+ {
+ if (nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted "
+ "windows counter was [%d].\n", (void *) pDrawable, nxagentCorruptedWindows);
+ #endif
+
+ if (nxagentCorruptedWindows > 0)
+ {
+ nxagentCorruptedWindows--;
+ }
+
+ FreeResource(nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedId, RT_NONE);
+
+ if (nxagentSynchronization.pDrawable == pDrawable)
+ {
+ nxagentSynchronization.pDrawable = NULL;
+ }
+ }
+ }
+ else if (type == RT_NX_CORR_BACKGROUND)
+ {
+ pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable);
+
+ if (nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted "
+ "backgrounds counter was [%d].\n", (void *) pDrawable, nxagentCorruptedBackgrounds);
+ #endif
+
+ if (nxagentCorruptedBackgrounds > 0)
+ {
+ nxagentCorruptedBackgrounds--;
+ }
+
+ FreeResource(nxagentPixmapPriv(pRealPixmap) -> corruptedBackgroundId, RT_NONE);
+
+ if (nxagentSynchronization.pDrawable == pDrawable)
+ {
+ nxagentSynchronization.pDrawable = NULL;
+ }
+ }
+ }
+ else if (type == RT_NX_CORR_PIXMAP)
+ {
+ pRealPixmap = nxagentRealPixmap((PixmapPtr) pDrawable);
+
+ if (nxagentPixmapPriv(pRealPixmap) -> corruptedId != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyCorruptedResource: Removing resource at [%p]. Corrupted "
+ "pixmaps counter was [%d].\n", (void *) pDrawable, nxagentCorruptedPixmaps);
+ #endif
+
+ if (nxagentCorruptedPixmaps > 0)
+ {
+ nxagentCorruptedPixmaps--;
+ }
+
+ FreeResource(nxagentPixmapPriv(pRealPixmap) -> corruptedId, RT_NONE);
+
+ if (nxagentSynchronization.pDrawable == pDrawable)
+ {
+ nxagentSynchronization.pDrawable = NULL;
+ }
+ }
+ }
+}
+
+void nxagentCleanCorruptedDrawable(DrawablePtr pDrawable)
+{
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCleanCorruptedDrawable: Clearing out the corrupted drawable [%s][%p].\n",
+ nxagentDrawableType(pDrawable), (void *) pDrawable);
+ #endif
+
+ nxagentUnmarkCorruptedRegion(pDrawable, NullRegion);
+
+ if (nxagentDrawableBitmap(pDrawable) != NullPixmap)
+ {
+ nxagentDestroyDrawableBitmap(pDrawable);
+ }
+}
+
+void nxagentUnmarkExposedRegion(WindowPtr pWin, RegionPtr pRegion, RegionPtr pOther)
+{
+ RegionRec clipRegion;
+
+ if (pRegion != NullRegion && RegionNil(pRegion) == 0 &&
+ nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
+ {
+ RegionInit(&clipRegion, NullBox, 1);
+
+ RegionCopy(&clipRegion, pRegion);
+
+ if (pOther != NullRegion && RegionNil(pOther) == 0)
+ {
+ RegionUnion(&clipRegion, &clipRegion, pOther);
+ }
+
+ RegionTranslate(&clipRegion, -pWin -> drawable.x, -pWin -> drawable.y);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUnmarkExposedRegion: Validating expose region [%d,%d,%d,%d] "
+ "on window [%p].\n", clipRegion.extents.x1, clipRegion.extents.y1,
+ clipRegion.extents.x2, clipRegion.extents.y2, (void *) pWin);
+ #endif
+
+ nxagentUnmarkCorruptedRegion((DrawablePtr) pWin, &clipRegion);
+
+ RegionUninit(&clipRegion);
+ }
+}
+
+int nxagentSynchronizationPredicate()
+{
+ if (nxagentCorruptedWindows == 0 &&
+ nxagentCorruptedBackgrounds == 0 &&
+ nxagentCorruptedPixmaps == 0)
+ {
+ return NotNeeded;
+ }
+
+ if (nxagentBlocking == 0 &&
+ nxagentCongestion <= 4 &&
+ nxagentReady == 0 &&
+ nxagentUserInput(NULL) == 0)
+ {
+ return Needed;
+ }
+
+ /*
+ * If there are resources to synchronize
+ * but the conditions to start the loop
+ * are not satisfied, a little delay is
+ * requested to check for a new loop as
+ * soon as possible.
+ */
+
+ return Delayed;
+}
+
+void nxagentSendBackgroundExpose(WindowPtr pWin, PixmapPtr pBackground, RegionPtr pExpose)
+{
+ RegionRec expose;
+ miBSWindowPtr pBackingStore;
+
+ RegionInit(&expose, NullBox, 1);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSendBackgroundExpose: Original expose region is [%d,%d,%d,%d].\n",
+ pExpose -> extents.x1, pExpose -> extents.y1,
+ pExpose -> extents.x2, pExpose -> extents.y2);
+
+ fprintf(stderr, "nxagentSendBackgroundExpose: Window clipList is [%d,%d,%d,%d].\n",
+ pWin -> clipList.extents.x1, pWin -> clipList.extents.y1,
+ pWin -> clipList.extents.x2, pWin -> clipList.extents.y2);
+ #endif
+
+ if (nxagentDrawableStatus((DrawablePtr) pBackground) == Synchronized &&
+ (pBackground -> drawable.width < pWin -> drawable.width ||
+ pBackground -> drawable.height < pWin -> drawable.height))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSendBackgroundExpose: Pixmap background [%dx%d] is "
+ "smaller than window [%dx%d]. Going to expose the winSize.\n",
+ pBackground -> drawable.width, pBackground -> drawable.height,
+ pWin -> drawable.width, pWin -> drawable.height);
+ #endif
+
+ RegionCopy(&expose, &pWin -> winSize);
+ }
+ else
+ {
+ RegionCopy(&expose, pExpose);
+
+ RegionTranslate(&expose, pWin -> drawable.x, pWin -> drawable.y);
+ }
+
+ RegionSubtract(&expose, &expose, nxagentCorruptedRegion((DrawablePtr) pWin));
+
+ if (RegionNil(&pWin -> clipList) != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSendBackgroundExpose: Exposures deferred because the window "
+ "is hidden.\n");
+ #endif
+
+ RegionUnion(nxagentDeferredBackgroundExposures,
+ nxagentDeferredBackgroundExposures, &expose);
+
+ nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 1;
+
+ goto nxagentSendBackgroundExposeEnd;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSendBackgroundExpose: Sending expose [%d,%d,%d,%d].\n",
+ expose.extents.x1, expose.extents.y1, expose.extents.x2, expose.extents.y2);
+ #endif
+
+ /*
+ * This prevents hidden region to be exposed.
+ */
+
+ pBackingStore = (miBSWindowPtr)pWin->backStorage;
+
+ if ((pBackingStore != NULL) && (RegionNil(&pBackingStore->SavedRegion) == 0))
+ {
+ RegionTranslate(&expose, -pWin -> drawable.x, -pWin -> drawable.y);
+
+ RegionSubtract(&expose, &expose, &pBackingStore -> SavedRegion);
+
+ RegionTranslate(&expose, pWin -> drawable.x, pWin -> drawable.y);
+ }
+
+ RegionIntersect(&expose, &expose, &pWin -> clipList);
+
+ /*
+ * Reduce the overall region to expose.
+ */
+
+ RegionTranslate(&expose, -pWin -> drawable.x, -pWin -> drawable.y);
+
+ RegionSubtract(pExpose, pExpose, &expose);
+
+ RegionTranslate(&expose, pWin -> drawable.x, pWin -> drawable.y);
+
+ miWindowExposures(pWin, &expose, &expose);
+
+nxagentSendBackgroundExposeEnd:
+
+ RegionUninit(&expose);
+}
+
+void nxagentExposeBackgroundPredicate(void *p0, XID x1, void *p2)
+{
+ WindowPtr pWin = (WindowPtr) p0;
+ WindowPtr pParent;
+
+ struct nxagentExposeBackground *pPair = p2;
+
+ if (RegionNil(pPair -> pExpose) != 0)
+ {
+ return;
+ }
+
+ if (pWin -> backgroundState == BackgroundPixmap &&
+ pWin -> background.pixmap == pPair -> pBackground)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExposeBackgroundPredicate: Window at [%p] uses pixmap [%p] "
+ "as background.\n", (void *) pWin, (void *) pPair -> pBackground);
+ #endif
+
+ nxagentSendBackgroundExpose(pWin, pPair -> pBackground, pPair -> pExpose);
+ }
+ else if (pWin -> backgroundState == ParentRelative)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExposeBackgroundPredicate: Window [%p] uses parent's background.\n",
+ (void *) pWin);
+ #endif
+
+ pParent = pWin -> parent;
+
+ while (pParent != NULL)
+ {
+ if (pParent -> backgroundState == BackgroundPixmap &&
+ pParent -> background.pixmap == pPair -> pBackground)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExposeBackgroundPredicate: Parent window at [%p] uses pixmap [%p] "
+ "as background.\n", (void *) pParent, (void *) pPair -> pBackground);
+ #endif
+
+ nxagentSendBackgroundExpose(pWin, pPair -> pBackground, pPair -> pExpose);
+
+ break;
+ }
+
+ pParent = pParent -> parent;
+ }
+ }
+}
+
+/*
+ * This function is similar to nxagentClipAndSendExpose().
+ */
+
+int nxagentClipAndSendClearExpose(WindowPtr pWin, void * ptr)
+{
+ RegionPtr exposeRgn;
+ RegionPtr remoteExposeRgn;
+
+ #ifdef DEBUG
+ BoxRec box;
+ #endif
+
+ remoteExposeRgn = (RegionRec *) ptr;
+
+ if (nxagentWindowPriv(pWin) -> deferredBackgroundExpose == 1)
+ {
+ exposeRgn = RegionCreate(NULL, 1);
+
+ #ifdef DEBUG
+ box = *RegionExtents(remoteExposeRgn);
+
+ fprintf(stderr, "nxagentClipAndSendClearExpose: Background expose extents: [%d,%d,%d,%d].\n",
+ box.x1, box.y1, box.x2, box.y2);
+
+ box = *RegionExtents(&pWin -> clipList);
+
+ fprintf(stderr, "nxagentClipAndSendClearExpose: Clip list extents for window at [%p]: [%d,%d,%d,%d].\n",
+ (void *) pWin, box.x1, box.y1, box.x2, box.y2);
+ #endif
+
+ RegionIntersect(exposeRgn, remoteExposeRgn, &pWin -> clipList);
+
+ /*
+ * If the region will be synchronized,
+ * the expose on corrupted regions can
+ * be ignored.
+ */
+
+ RegionSubtract(exposeRgn, exposeRgn, nxagentCorruptedRegion((DrawablePtr) pWin));
+
+ if (RegionNotEmpty(exposeRgn))
+ {
+ #ifdef DEBUG
+ box = *RegionExtents(exposeRgn);
+
+ fprintf(stderr, "nxagentClipAndSendClearExpose: Forwarding expose [%d,%d,%d,%d] to window at [%p] pWin.\n",
+ box.x1, box.y1, box.x2, box.y2, (void *) pWin);
+ #endif
+
+ RegionSubtract(remoteExposeRgn, remoteExposeRgn, exposeRgn);
+
+ miWindowExposures(pWin, exposeRgn, exposeRgn);
+ }
+
+ RegionDestroy(exposeRgn);
+
+ nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 0;
+ }
+
+ if (RegionNotEmpty(remoteExposeRgn))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClipAndSendClearExpose: Region not empty. Walk children.\n");
+ #endif
+
+
+ return WT_WALKCHILDREN;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClipAndSendClearExpose: Region empty. Stop walking.\n");
+ #endif
+
+ return WT_STOPWALKING;
+ }
+}
+
+void nxagentSendDeferredBackgroundExposures(void)
+{
+ if (nxagentDeferredBackgroundExposures == NullRegion)
+ {
+ nxagentDeferredBackgroundExposures = RegionCreate(NullBox, 1);
+ }
+
+ if (RegionNotEmpty(nxagentDeferredBackgroundExposures) != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSendDeferredBackgroundExposures: Going to send deferred exposures to the root window.\n");
+ #endif
+
+ TraverseTree(screenInfo.screens[0]->root, nxagentClipAndSendClearExpose, (void *) nxagentDeferredBackgroundExposures);
+
+ RegionEmpty(nxagentDeferredBackgroundExposures);
+ }
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Drawable.h b/nx-X11/programs/Xserver/hw/nxagent/Drawable.h
new file mode 100644
index 000000000..6388d5c12
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Drawable.h
@@ -0,0 +1,229 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Drawable_H__
+#define __Drawable_H__
+
+#include "resource.h"
+#include "Windows.h"
+#include "Pixmaps.h"
+
+/*
+ * Structures and macros used to manage the Lazy encoding.
+ */
+
+typedef struct
+{
+ DrawablePtr pDrawable;
+ int drawableType;
+ int abort;
+ int windowBitmaps;
+ int pixmapBitmaps;
+ int backgroundBitmaps;
+
+} _nxagentSynchronizationRec;
+
+extern _nxagentSynchronizationRec nxagentSynchronization;
+
+enum DrawableStatus
+{
+ Synchronized,
+ NotSynchronized
+};
+
+enum SynchronizationPredicate
+{
+ Needed,
+ NotNeeded,
+ Delayed
+};
+
+/*
+ * Shall the synchronization wait for the
+ * drawable wakening?
+ */
+
+#define DONT_WAIT 0
+#define DO_WAIT 1
+
+/*
+ * How the synchronization loop can be
+ * interrupted? A 0 mask means that the
+ * loop can't be stopped.
+ */
+
+#define EVENT_BREAK (1 << 0)
+#define CONGESTION_BREAK (1 << 1)
+#define BLOCKING_BREAK (1 << 2)
+
+#define NEVER_BREAK 0
+#define ALWAYS_BREAK (EVENT_BREAK | \
+ CONGESTION_BREAK | \
+ BLOCKING_BREAK)
+
+/*
+ * Minimum value of usage counter which
+ * a pixmap should have to be synchronized.
+ */
+
+#define MINIMUM_PIXMAP_USAGE_COUNTER 2
+
+/*
+ * This is the macro used to get the external XID
+ * from a generic pointer to a drawable.
+ */
+
+#define nxagentDrawable(pDrawable) \
+ ((pDrawable)->type == DRAWABLE_WINDOW ? \
+ nxagentWindow((WindowPtr)pDrawable) : \
+ nxagentPixmap((PixmapPtr)pDrawable))
+
+#define nxagentVirtualDrawable(pDrawable) \
+ (DrawablePtr)((pDrawable)->type == DRAWABLE_WINDOW ? \
+ NULL : nxagentVirtualPixmap((PixmapPtr)pDrawable))
+
+#define nxagentDrawablePicture(pDrawable) \
+ ((DrawablePtr)((pDrawable)->type == DRAWABLE_WINDOW ? \
+ nxagentWindowPriv((WindowPtr)pDrawable) -> pPicture : \
+ nxagentPixmapPriv((PixmapPtr)pDrawable) -> pPicture))
+
+#define nxagentCorruptedRegion(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? \
+ nxagentPixmapCorruptedRegion((PixmapPtr) pDrawable) : \
+ nxagentWindowCorruptedRegion((WindowPtr) pDrawable))
+
+#define nxagentDrawableStatus(pDrawable) \
+ (RegionNil(nxagentCorruptedRegion(pDrawable)) ? \
+ Synchronized : NotSynchronized)
+
+#define nxagentDrawableContainGlyphs(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? \
+ nxagentPixmapContainGlyphs((PixmapPtr) (pDrawable)) : \
+ nxagentWindowContainGlyphs((WindowPtr) (pDrawable)))
+
+#define nxagentSetDrawableContainGlyphs(pDrawable, value) \
+do \
+{ \
+ if ((pDrawable) -> type == DRAWABLE_PIXMAP) \
+ { \
+ nxagentPixmapContainGlyphs(nxagentRealPixmap((PixmapPtr) (pDrawable))) = (value); \
+ } \
+ else \
+ { \
+ nxagentWindowContainGlyphs((WindowPtr) (pDrawable)) = (value); \
+ } \
+} while (0)
+
+#define nxagentDrawableBitmap(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? \
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) (pDrawable))) -> synchronizationBitmap : \
+ nxagentWindowPriv((WindowPtr) (pDrawable)) -> synchronizationBitmap)
+
+#define nxagentDrawableTimestamp(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? \
+ nxagentPixmapTimestamp((PixmapPtr) pDrawable) : \
+ nxagentWindowTimestamp((WindowPtr) pDrawable))
+
+#define nxagentDrawableType(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? "pixmap" : "window")
+
+extern RESTYPE RT_NX_CORR_BACKGROUND;
+extern RESTYPE RT_NX_CORR_WINDOW;
+extern RESTYPE RT_NX_CORR_PIXMAP;
+
+extern int nxagentCorruptedPixmaps;
+extern int nxagentCorruptedWindows;
+extern int nxagentCorruptedBackgrounds;
+
+extern int nxagentForceSynchronization;
+
+extern RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int width, int height);
+
+#define nxagentFreeRegion(pDrawable, pRegion) \
+ RegionDestroy(pRegion);
+
+extern void nxagentMarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion);
+extern void nxagentUnmarkCorruptedRegion(DrawablePtr pDrawable, RegionPtr pRegion);
+extern void nxagentMoveCorruptedRegion(WindowPtr pWin, unsigned int mask);
+extern void nxagentIncreasePixmapUsageCounter(PixmapPtr pPixmap);
+
+extern int nxagentSynchronizeRegion(DrawablePtr pDrawable, RegionPtr pRegion, unsigned int breakMask, WindowPtr owner);
+extern void nxagentSynchronizeBox(DrawablePtr pDrawable, BoxPtr pBox, unsigned int breakMask);
+extern int nxagentSynchronizeDrawable(DrawablePtr pDrawable, int wait, unsigned int breakMask, WindowPtr owner);
+extern int nxagentSynchronizeDrawableData(DrawablePtr pDrawable, unsigned int breakMask, WindowPtr owner);
+extern void nxagentSynchronizationLoop(unsigned int mask);
+
+extern int nxagentSynchronizationPredicate(void);
+
+extern BoxPtr nxagentGetOptimizedRegionBoxes(RegionPtr pRegion);
+
+extern void nxagentCleanCorruptedDrawable(DrawablePtr pDrawable);
+
+extern void nxagentUnmarkExposedRegion(WindowPtr pWin, RegionPtr pRegion, RegionPtr pOther);
+extern void nxagentSendDeferredBackgroundExposures(void);
+
+extern void nxagentClearRegion(DrawablePtr pDrawable, RegionPtr pRegion);
+extern void nxagentFillRemoteRegion(DrawablePtr pDrawable, RegionPtr pRegion);
+
+extern void nxagentAllocateCorruptedResource(DrawablePtr pDrawable, RESTYPE type);
+extern void nxagentDestroyCorruptedResource(DrawablePtr pDrawable, RESTYPE type);
+extern int nxagentDestroyCorruptedBackgroundResource(void * p, XID id);
+extern int nxagentDestroyCorruptedWindowResource(void * p, XID id);
+extern int nxagentDestroyCorruptedPixmapResource(void * p, XID id);
+
+extern void nxagentCreateDrawableBitmap(DrawablePtr pDrawable);
+extern void nxagentDestroyDrawableBitmap(DrawablePtr pDrawable);
+
+extern void nxagentRegionsOnScreen(void);
+
+#define PRINT_REGION_BOXES(pRegion, strRegion) \
+do \
+{ \
+ int i; \
+ int numRects; \
+ BoxPtr pBox; \
+\
+ if (pRegion == NullRegion) \
+ { \
+ fprintf(stderr, "printRegionBoxes:: Region " strRegion " is null.\n"); \
+ break; \
+ } \
+\
+ numRects = RegionNumRects(pRegion); \
+ pBox = RegionRects(pRegion); \
+\
+ fprintf(stderr, "printRegionBoxes:: Region " strRegion " at [%p] has [%d] boxes:\n", \
+ (void *) (pRegion), numRects); \
+\
+ for (i = 0; i < numRects; i++) \
+ { \
+ fprintf(stderr, "[%d] [%d,%d,%d,%d]\n", \
+ i, pBox[i].x1, pBox[i].y1, pBox[i].x2, pBox[i].y2); \
+ } \
+\
+} while (0)
+
+#endif /* __Drawable_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Error.c b/nx-X11/programs/Xserver/hw/nxagent/Error.c
new file mode 100644
index 000000000..05d0f3081
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Error.c
@@ -0,0 +1,644 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "os.h"
+
+#include "scrnintstr.h"
+#include "Agent.h"
+
+#include "Xlib.h"
+#include "Xproto.h"
+
+#include "Error.h"
+#include "Args.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+
+/*
+ * Duplicated stderr file descriptor.
+ */
+
+static int nxagentStderrDup = -1;
+
+/*
+ * Saved stderr file descriptor.
+ */
+
+static int nxagentStderrBackup = -1;
+
+/*
+ * Clients log file descriptor.
+ */
+
+static int nxagentClientsLog = -1;
+
+#define DEFAULT_STRING_LENGTH 256
+
+
+/*
+ * Clients log file name.
+ */
+
+char nxagentClientsLogName[DEFAULT_STRING_LENGTH] = { 0 };
+
+/*
+ * User's home.
+ */
+
+static char nxagentHomeDir[DEFAULT_STRING_LENGTH] = { 0 };
+
+/*
+ * NX root directory.
+ */
+
+static char nxagentRootDir[DEFAULT_STRING_LENGTH] = { 0 };
+
+/*
+ * Session log Directory.
+ */
+
+static char nxagentSessionDir[DEFAULT_STRING_LENGTH] = { 0 };
+
+char *nxagentGetClientsPath(void);
+
+static int nxagentPrintError(Display *dpy, XErrorEvent *event, FILE *fp);
+
+/* declare an error handler that does not exit when an error
+ * event is catched.
+ */
+
+int nxagentErrorHandler(Display *dpy, XErrorEvent *event)
+{
+ if (nxagentVerbose == 1)
+ {
+ nxagentPrintError(dpy, event, stderr);
+ }
+
+ return 0;
+}
+
+/* copied from XlibInt.c */
+/* extension stuff roughly commented out */
+static int nxagentPrintError(dpy, event, fp)
+ Display *dpy;
+ XErrorEvent *event;
+ FILE *fp;
+{
+ char buffer[BUFSIZ];
+ char mesg[BUFSIZ];
+ char number[32];
+ char *mtype = "XlibMessage";
+ /*
+ register _XExtension *ext = (_XExtension *)NULL;
+ _XExtension *bext = (_XExtension *)NULL;
+ */
+ XGetErrorText(dpy, event->error_code, buffer, BUFSIZ);
+ XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ);
+ (void) fprintf(fp, "%s: %s\n ", mesg, buffer);
+ XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d",
+ mesg, BUFSIZ);
+ (void) fprintf(fp, mesg, event->request_code);
+ if (event->request_code < 128) {
+ sprintf(number, "%d", event->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ);
+ } else {
+ /* for (ext = dpy->ext_procs;
+ ext && (ext->codes.major_opcode != event->request_code);
+ ext = ext->next)
+ ;
+ if (ext)
+ strcpy(buffer, ext->name);
+ else
+ */
+ buffer[0] = '\0';
+ }
+ (void) fprintf(fp, " (%s)\n", buffer);
+ if (event->request_code >= 128) {
+ XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d",
+ mesg, BUFSIZ);
+ fputs(" ", fp);
+ (void) fprintf(fp, mesg, event->minor_code);
+ /*
+ if (ext) {
+ sprintf(mesg, "%s.%d", ext->name, event->minor_code);
+ XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ);
+ (void) fprintf(fp, " (%s)", buffer);
+ }
+ */
+ fputs("\n", fp);
+ }
+ if (event->error_code >= 128) {
+ /* kludge, try to find the extension that caused it */
+ buffer[0] = '\0';
+ /*
+ for (ext = dpy->ext_procs; ext; ext = ext->next) {
+ if (ext->error_string)
+ (*ext->error_string)(dpy, event->error_code, &ext->codes,
+ buffer, BUFSIZ);
+ if (buffer[0]) {
+ bext = ext;
+ break;
+ }
+ if (ext->codes.first_error &&
+ ext->codes.first_error < (int)event->error_code &&
+ (!bext || ext->codes.first_error > bext->codes.first_error))
+ bext = ext;
+ }
+ if (bext)
+ sprintf(buffer, "%s.%d", bext->name,
+ event->error_code - bext->codes.first_error);
+ else
+ */
+ strcpy(buffer, "Value");
+ XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ);
+ if (mesg[0]) {
+ fputs(" ", fp);
+ (void) fprintf(fp, mesg, event->resourceid);
+ fputs("\n", fp);
+ }
+ /* let extensions try to print the values */
+ /*
+ for (ext = dpy->ext_procs; ext; ext = ext->next) {
+ if (ext->error_values)
+ (*ext->error_values)(dpy, event, fp);
+ }
+ */
+ } else if ((event->error_code == BadWindow) ||
+ (event->error_code == BadPixmap) ||
+ (event->error_code == BadCursor) ||
+ (event->error_code == BadFont) ||
+ (event->error_code == BadDrawable) ||
+ (event->error_code == BadColor) ||
+ (event->error_code == BadGC) ||
+ (event->error_code == BadIDChoice) ||
+ (event->error_code == BadValue) ||
+ (event->error_code == BadAtom)) {
+ if (event->error_code == BadValue)
+ XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x",
+ mesg, BUFSIZ);
+ else if (event->error_code == BadAtom)
+ XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x",
+ mesg, BUFSIZ);
+ else
+ XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x",
+ mesg, BUFSIZ);
+ fputs(" ", fp);
+ (void) fprintf(fp, mesg, event->resourceid);
+ fputs("\n", fp);
+ }
+ XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d",
+ mesg, BUFSIZ);
+ fputs(" ", fp);
+ (void) fprintf(fp, mesg, event->serial);
+ XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d",
+ mesg, BUFSIZ);
+ fputs("\n ", fp);
+ /* (void) fprintf(fp, mesg, dpy->request); */
+ fputs("\n", fp);
+ if (event->error_code == BadImplementation) return 0;
+ return 1;
+}
+
+int nxagentExitHandler(const char *message)
+{
+ FatalError("%s", message);
+
+ return 0;
+}
+
+void nxagentOpenClientsLogFile()
+{
+ char * clientsLogName;
+
+ if (*nxagentClientsLogName == '\0')
+ {
+ clientsLogName = nxagentGetClientsPath();
+
+ if (clientsLogName != NULL)
+ {
+ free(clientsLogName);
+ }
+ }
+
+ if (nxagentClientsLogName != NULL && *nxagentClientsLogName !='\0')
+ {
+ nxagentClientsLog = open(nxagentClientsLogName, O_RDWR | O_CREAT | O_APPEND, 0600);
+
+ if (nxagentClientsLog == -1)
+ {
+ fprintf(stderr, "Warning: Failed to open clients log. Error is %d '%s'.\n",
+ errno, strerror(errno));
+ }
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenClientsLogFile: Cannot open clients log file. The path does not exist.\n");
+ #endif
+ }
+}
+
+void nxagentCloseClientsLogFile(void)
+{
+ close(nxagentClientsLog);
+}
+
+void nxagentStartRedirectToClientsLog(void)
+{
+ nxagentOpenClientsLogFile();
+
+ if (nxagentClientsLog != -1)
+ {
+ if (nxagentStderrBackup == -1)
+ {
+ nxagentStderrBackup = dup(2);
+ }
+
+ if (nxagentStderrBackup != -1)
+ {
+ nxagentStderrDup = dup2(nxagentClientsLog, 2);
+
+ if (nxagentStderrDup == -1)
+ {
+ fprintf(stderr, "Warning: Failed to redirect stderr. Error is %d '%s'.\n",
+ errno, strerror(errno));
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Warning: Failed to backup stderr. Error is %d '%s'.\n",
+ errno, strerror(errno));
+ }
+ }
+}
+
+void nxagentEndRedirectToClientsLog(void)
+{
+ if (nxagentStderrBackup != -1)
+ {
+ nxagentStderrDup = dup2(nxagentStderrBackup, 2);
+
+ if (nxagentStderrDup == -1)
+ {
+ fprintf(stderr, "Warning: Failed to restore stderr. Error is %d '%s'.\n",
+ errno, strerror(errno));
+ }
+ }
+
+ nxagentCloseClientsLogFile();
+}
+
+char *nxagentGetHomePath(void)
+{
+ char *homeEnv;
+ char *homePath;
+
+ if (*nxagentHomeDir == '\0')
+ {
+ /*
+ * Check the NX_HOME environment.
+ */
+
+ homeEnv = getenv("NX_HOME");
+
+ if (homeEnv == NULL || *homeEnv == '\0')
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetHomePath: No environment for NX_HOME.\n");
+ #endif
+
+ homeEnv = getenv("HOME");
+
+ if (homeEnv == NULL || *homeEnv == '\0')
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetHomePath: PANIC! No environment for HOME.\n");
+ #endif
+
+ return NULL;
+ }
+ }
+
+ if (strlen(homeEnv) > DEFAULT_STRING_LENGTH - 1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetHomePath: PANIC! Invalid value for the NX "
+ "home directory '%s'.\n", homeEnv);
+ #endif
+ }
+
+ strncpy(nxagentHomeDir, homeEnv, DEFAULT_STRING_LENGTH - 1);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetHomePath: Assuming NX user's home directory '%s'.\n", nxagentHomeDir);
+ #endif
+ }
+
+ homePath = (char*) malloc(strlen(nxagentHomeDir) + 1);
+
+ if (homePath == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetHomePath: PANIC! Can't allocate memory for the home path.\n");
+ #endif
+
+ return NULL;
+ }
+
+ strcpy(homePath, nxagentHomeDir);
+
+ return homePath;
+}
+
+char *nxagentGetRootPath(void)
+{
+ char *rootEnv;
+ char *homeEnv;
+ char *rootPath;
+
+ struct stat dirStat;
+
+ if (*nxagentRootDir == '\0')
+ {
+ /*
+ * Check the NX_ROOT environment.
+ */
+
+ rootEnv = getenv("NX_ROOT");
+
+ if (rootEnv == NULL || *rootEnv == '\0')
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetRootPath: WARNING! No environment for NX_ROOT.\n");
+ #endif
+
+ /*
+ * We will determine the root NX directory
+ * based on the NX_HOME or HOME directory
+ * settings.
+ */
+
+ homeEnv = nxagentGetHomePath();
+
+ if (homeEnv == NULL)
+ {
+
+ #ifdef PANIC
+ #endif
+
+ return NULL;
+ }
+
+ if (strlen(homeEnv) > DEFAULT_STRING_LENGTH -
+ strlen("/.nx") - 1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetRootPath: PANIC! Invalid value for the NX "
+ "home directory '%s'.\n", homeEnv);
+ #endif
+
+ free(homeEnv);
+
+ return NULL;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetRootPath: Assuming NX root directory in '%s'.\n", homeEnv);
+ #endif
+
+ strcpy(nxagentRootDir, homeEnv);
+ strcat(nxagentRootDir, "/.nx");
+
+ free(homeEnv);
+
+ /*
+ * Create the NX root directory.
+ */
+
+ if ((stat(nxagentRootDir, &dirStat) == -1) && (errno == ENOENT))
+ {
+ if (mkdir(nxagentRootDir, 0777) < 0 && (errno != EEXIST))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetRootPath: PANIC! Can't create directory '%s'. Error is %d '%s'.\n",
+ nxagentRootDir, errno, strerror(errno));
+ #endif
+
+ return NULL;
+ }
+ }
+ }
+ else
+ {
+ if (strlen(rootEnv) > DEFAULT_STRING_LENGTH - 1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetRootPath: PANIC! Invalid value for the NX root directory '%s'.\n",
+ rootEnv);
+ #endif
+
+ return NULL;
+ }
+
+ strcpy(nxagentRootDir, rootEnv);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetRootPath: Assuming NX root directory '%s'.\n",
+ nxagentRootDir);
+ #endif
+
+ }
+
+ rootPath = malloc(strlen(nxagentRootDir) + 1);
+
+ if (rootPath == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetRootPath: Can't allocate memory for the root path.\n");
+ #endif
+
+ return NULL;
+ }
+
+ strcpy(rootPath, nxagentRootDir);
+
+ return rootPath;
+}
+
+char *nxagentGetSessionPath(void)
+{
+
+ char *rootPath;
+ char *sessionPath;
+
+ struct stat dirStat;
+
+ if (*nxagentSessionDir == '\0')
+ {
+ /*
+ * If nxagentSessionId does not exist we
+ * assume that the sessionPath cannot be
+ * realized and do not use the clients
+ * log file.
+ */
+
+ if (*nxagentSessionId == '\0')
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetSessionPath: Session id does not exist. Assuming session path NULL.\n");
+ #endif
+
+ return NULL;
+ }
+
+ rootPath = nxagentGetRootPath();
+
+ if (rootPath == NULL)
+ {
+ return NULL;
+ }
+
+ strcpy(nxagentSessionDir, rootPath);
+
+ free(rootPath);
+
+ if (strlen(nxagentSessionDir) + strlen("/C-") + strlen(nxagentSessionId) > DEFAULT_STRING_LENGTH - 1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetSessionPath: PANIC!: Invalid value for the NX session directory '%s'.\n",
+ nxagentSessionDir);
+ #endif
+
+ return NULL;
+ }
+
+ strcat(nxagentSessionDir, "/C-");
+
+ strcat(nxagentSessionDir, nxagentSessionId);
+
+ if ((stat(nxagentSessionDir, &dirStat) == -1) && (errno == ENOENT))
+ {
+ if (mkdir(nxagentSessionDir, 0777) < 0 && (errno != EEXIST))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetSessionPath: PANIC! Can't create directory '%s'. Error is %d '%s'.\n",
+ nxagentSessionDir, errno, strerror(errno));
+ #endif
+
+ return NULL;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetSessionPath: NX session is '%s'.\n",
+ nxagentSessionDir);
+ #endif
+
+ }
+
+ sessionPath = malloc(strlen(nxagentSessionDir) + 1);
+
+ if (sessionPath == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetSessionPath:: PANIC! Can't allocate memory for the session path.\n");
+ #endif
+
+ return NULL;
+ }
+
+
+ strcpy(sessionPath, nxagentSessionDir);
+
+ return sessionPath;
+}
+
+char *nxagentGetClientsPath()
+{
+ char *sessionPath;
+ char *clientsPath;
+
+ if (*nxagentClientsLogName == '\0')
+ {
+ sessionPath = nxagentGetSessionPath();
+
+ if (sessionPath == NULL)
+ {
+ return NULL;
+ }
+
+ if (strlen(sessionPath) + strlen("/clients") > DEFAULT_STRING_LENGTH - 1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetClientsPath: PANIC! Invalid value for the NX clients Log File Path '%s'.\n",
+ nxagentClientsLogName);
+ #endif
+
+ free(sessionPath);
+
+ return NULL;
+ }
+
+ strcpy(nxagentClientsLogName, sessionPath);
+
+ strcat(nxagentClientsLogName, "/clients");
+
+ free(sessionPath);
+ }
+
+ clientsPath = malloc(strlen(nxagentClientsLogName) + 1);
+
+ if (clientsPath == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentGetClientsPath: PANIC! Can't allocate memory for the clients Log File Path path.\n");
+ #endif
+
+ return NULL;
+ }
+
+ strcpy(clientsPath, nxagentClientsLogName);
+
+ return clientsPath;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Error.h b/nx-X11/programs/Xserver/hw/nxagent/Error.h
new file mode 100644
index 000000000..1d0d9a827
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Error.h
@@ -0,0 +1,47 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Error_H__
+#define __Error_H__
+
+/*
+ * Clients log file name.
+ */
+
+extern char nxagentClientsLogName[];
+
+extern char nxagentVerbose;
+
+int nxagentErrorHandler(Display *dpy, XErrorEvent *event);
+
+int nxagentExitHandler(const char *message);
+
+void nxagentStartRedirectToClientsLog(void);
+
+void nxagentEndRedirectToClientsLog(void);
+
+char *nxagentGetSessionPath(void);
+
+#endif /* __Error_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.c b/nx-X11/programs/Xserver/hw/nxagent/Events.c
new file mode 100644
index 000000000..e360d21f6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Events.c
@@ -0,0 +1,4767 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "X.h"
+#include "signal.h"
+#include "unistd.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "dix.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mi.h"
+#include "selection.h"
+#include "keysym.h"
+#include "fb.h"
+#include "mibstorest.h"
+#include "osdep.h"
+
+#include "Agent.h"
+#include "Args.h"
+#include "Atoms.h"
+#include "Colormap.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Windows.h"
+#include "Pixmaps.h"
+#include "Keyboard.h"
+#include "Keystroke.h"
+#include "Events.h"
+#include "Pointer.h"
+#include "Rootless.h"
+#include "Splash.h"
+#include "Trap.h"
+#include "Dialog.h"
+#include "Client.h"
+#include "Clipboard.h"
+#include "Split.h"
+#include "Drawable.h"
+#include "Handlers.h"
+#include "Utils.h"
+#include "Error.h"
+
+#include <nx/NX.h>
+#include <nx/NXvars.h>
+#include <nx/NXproto.h>
+
+#include "xfixesproto.h"
+#define Window XlibWindow
+#define Atom XlibAtom
+#define Time XlibXID
+#include "X11/include/Xfixes_nxagent.h"
+#undef Window
+#undef Atom
+#undef Time
+
+#ifdef NXAGENT_FIXKEYS
+#include "inputstr.h"
+#include "input.h"
+#endif
+
+#define Time XlibXID
+#include "XKBlib.h"
+#undef Time
+
+#define GC XlibGC
+#define Font XlibFont
+#define KeySym XlibKeySym
+#define XID XlibXID
+#include "Xlibint.h"
+#undef GC
+#undef Font
+#undef KeySym
+#undef XID
+
+#include <nx-X11/cursorfont.h>
+
+#include <nx/Shadow.h>
+#include "X11/include/Xrandr_nxagent.h"
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level. Please note
+ * that if you want to enable DEBUG here, then
+ * you need to enable DEBUG even in Rootless.c
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Log begin and end of the important handlers.
+ */
+
+#undef BLOCKS
+
+extern Bool nxagentOnce;
+
+extern WindowPtr nxagentRootTileWindow;
+extern int nxagentSplashCount;
+
+extern int nxagentLastClipboardClient;
+
+#ifdef NX_DEBUG_INPUT
+int nxagentDebugInput = 0;
+#endif
+
+#ifdef DEBUG
+extern Bool nxagentRootlessTreesMatch(void);
+#endif
+
+extern Selection *CurrentSelections;
+extern int NumCurrentSelections;
+
+typedef union _XFixesSelectionEvent {
+ int type;
+ XFixesSelectionNotifyEvent xfixesselection;
+ XEvent core;
+} XFixesSelectionEvent;
+
+Bool xkbdRunning = False;
+pid_t pidkbd;
+
+WindowPtr nxagentLastEnteredWindow = NULL;
+
+PropertyRequestRec nxagentPropertyRequests[NXNumberOfResources];
+
+void nxagentHandleCollectPropertyEvent(XEvent*);
+
+/*
+ * Finalize the asynchronous handling
+ * of the X_GrabPointer requests.
+ */
+
+void nxagentHandleCollectGrabPointerEvent(int resource);
+
+Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr);
+
+/*
+ * Used in Handlers.c to synchronize
+ * the agent with the remote X server.
+ */
+
+void nxagentHandleCollectInputFocusEvent(int resource);
+
+/*
+ * Viewport navigation.
+ */
+
+static int viewportInc = 1;
+static enum HandleEventResult viewportLastKeyPressResult;
+static int viewportLastX;
+static int viewportLastY;
+static Cursor viewportCursor;
+
+#define MAX_INC 200
+#define INC_STEP 5
+#define nextinc(x) ((x) < MAX_INC ? (x) += INC_STEP : (x))
+
+/*
+ * Keyboard and pointer are handled as they were real devices by
+ * Xnest and we inherit this behaviour. The following mask will
+ * contain the event mask selected for the root window of the
+ * agent. All the keyboard and pointer events will be translated
+ * by the agent and sent to the internal clients according to
+ * events selected by the inferior windows.
+ */
+
+static Mask defaultEventMask;
+
+static int lastEventSerial = 0;
+
+/*
+ * Used to mask the appropriate bits in
+ * the state reported by XkbStateNotify
+ * and XkbGetIndicatorState.
+ */
+
+#define CAPSFLAG_IN_REPLY 1
+#define CAPSFLAG_IN_EVENT 2
+#define NUMFLAG_IN_EVENT 16
+#define NUMFLAG_IN_REPLY 2
+
+CARD32 nxagentLastEventTime = 0;
+CARD32 nxagentLastKeyPressTime = 0;
+Time nxagentLastServerTime = 0;
+
+/*
+ * Used for storing windows that need to
+ * receive expose events from the agent.
+ */
+
+#define nxagentExposeQueueHead nxagentExposeQueue.exposures[nxagentExposeQueue.start]
+
+ExposeQueue nxagentExposeQueue;
+
+RegionPtr nxagentRemoteExposeRegion = NULL;
+
+static void nxagentForwardRemoteExpose(void);
+
+static int nxagentClipAndSendExpose(WindowPtr pWin, void * ptr);
+
+/*
+ * This is from NXproperty.c.
+ */
+
+int GetWindowProperty(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);
+
+/*
+ * Associate a resource to a drawable and
+ * store the region affected by the split
+ * operation.
+ */
+
+SplitResourceRec nxagentSplitResources[NXNumberOfResources];
+
+/*
+ * Associate a resource to an unpack
+ * operation.
+ */
+
+UnpackResourceRec nxagentUnpackResources[NXNumberOfResources];
+
+/*
+ * We have to check these before launching
+ * the terminate dialog in rootless mode.
+ */
+
+Bool nxagentLastWindowDestroyed = False;
+Time nxagentLastWindowDestroyedTime = 0;
+
+/*
+ * Set this flag when an user input event
+ * is received.
+ */
+
+int nxagentInputEvent = 0;
+
+int nxagentKeyDown = 0;
+
+void nxagentSwitchResizeMode(ScreenPtr pScreen);
+
+int nxagentCheckWindowConfiguration(XConfigureEvent* X);
+
+#define nxagentMonitoredDuplicate(keysym) \
+ ((keysym) == XK_Left || (keysym) == XK_Up || \
+ (keysym) == XK_Right || (keysym) == XK_Down || \
+ (keysym) == XK_Page_Up || (keysym) == XK_Page_Down || \
+ (keysym) == XK_Delete || (keysym) == XK_BackSpace)
+
+void nxagentRemoveDuplicatedKeys(XEvent *X);
+
+void ProcessInputEvents()
+{
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "ProcessInputEvents: Processing input.\n");
+ }
+ #endif
+
+ mieqProcessInputEvents();
+}
+
+#ifdef DEBUG_TREE
+
+/*
+ * Print ID and name of window.
+ */
+
+void nxagentRemoteWindowID(Window window, Bool newline)
+{
+#ifdef NO_I18N
+ char *winName;
+#else
+ XTextProperty tp;
+#endif
+
+ fprintf(stderr, "0x%lx", window);
+
+ if (!window)
+ {
+ fprintf(stderr, " (none) ");
+ }
+ else
+ {
+ if (window == DefaultRootWindow(nxagentDisplay))
+ {
+ fprintf(stderr, " (the root window) ");
+ }
+
+#ifdef NO_I18N
+
+ if (!XFetchName(nxagentDisplay, window, &winName))
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ else if (winName)
+ {
+ fprintf(stderr, " \"%s\" ", winName);
+ XFree(winName);
+ }
+
+#else
+
+ if (XGetWMName(nxagentDisplay, window, &tp) != 0)
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ else if (tp.nitems > 0)
+ {
+ int count = 0;
+ int i, ret;
+ char **list = NULL;
+
+ fprintf(stderr, " \"");
+
+ ret = XmbTextPropertyToTextList(nxagentDisplay, &tp, &list, &count);
+
+ if ((ret == Success || ret > 0) && list != NULL)
+ {
+ for (i = 0; i < count; i++)
+ {
+ fprintf(stderr, "%s", list[i]);
+ }
+
+ XFreeStringList(list);
+ }
+ else
+ {
+ fprintf(stderr, "%s", tp.value);
+ }
+
+ fprintf(stderr, "\" ");
+ }
+
+#endif
+
+ else
+ {
+ fprintf(stderr, " (has no name) ");
+ }
+ }
+
+ if (newline == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+
+ return;
+}
+
+/*
+ * Print info about remote window.
+ */
+
+void nxagentRemoteWindowInfo(Window win, int indent, Bool newLine)
+{
+ XWindowAttributes attributes;
+ int i;
+
+ if (XGetWindowAttributes(nxagentDisplay, win, &attributes) == 0)
+ {
+ return;
+ }
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "x=%d y=%d width=%d height=%d class=%s map_state=%s "
+ "override_redirect=%s\n", attributes.x, attributes.y,
+ attributes.width, attributes.height,
+ (attributes.class == 0) ? "CopyFromParent" :
+ ((attributes.class == 1) ? "InputOutput" : "InputOnly"),
+ (attributes.map_state == 0) ?
+ "IsUnmapped" : (attributes.map_state == 1 ?
+ "IsUnviewable" : "IsViewable"),
+ (attributes.override_redirect == 0) ?
+ "No" : "Yes" );
+
+ if (newLine == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * Walk remote windows tree.
+ */
+
+void nxagentRemoteWindowsTree(Window window, int level)
+{
+ int i, j;
+ unsigned long rootWin, parentWin;
+ unsigned int numChildren;
+ unsigned long *childList;
+
+ if (!XQueryTree(nxagentDisplay, window, &rootWin, &parentWin, &childList,
+ &numChildren))
+ {
+ fprintf(stderr, "nxagentRemoteWindowsTree - XQueryTree failed.\n");
+
+ return;
+ }
+
+ if (level == 0)
+ {
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Root Window ID: ");
+ nxagentRemoteWindowID(rootWin, TRUE);
+
+ fprintf(stderr, " Parent window ID: ");
+ nxagentRemoteWindowID(parentWin, TRUE);
+ }
+
+ if (level == 0 || numChildren > 0)
+ {
+ fprintf(stderr, " ");
+
+ for (j = 0; j < level; j++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "%d child%s%s\n", numChildren, (numChildren == 1) ? "" :
+ "ren", (numChildren == 1) ? ":" : ".");
+ }
+
+ for (i = (int) numChildren - 1; i >= 0; i--)
+ {
+ fprintf(stderr, " ");
+
+ for (j = 0; j < level; j++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ nxagentRemoteWindowID(childList[i], TRUE);
+
+ nxagentRemoteWindowInfo(childList[i], (level * 5) + 6, TRUE);
+
+ nxagentRemoteWindowsTree(childList[i], level + 1);
+ }
+
+ if (childList)
+ {
+ XFree((char *) childList);
+ }
+}
+
+/*
+ * Print info about internal window.
+ */
+
+void nxagentInternalWindowInfo(WindowPtr pWin, int indent, Bool newLine)
+{
+ int i;
+ int result;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ Atom atomReturnType;
+ int iReturnFormat;
+ unsigned char *pszReturnData = NULL;
+
+ fprintf(stderr, "Window ID=[0x%lx] Remote ID=[0x%lx] ", pWin -> drawable.id,
+ nxagentWindow(pWin));
+
+ result = GetWindowProperty(pWin, MakeAtom("WM_NAME", 7, False) , 0,
+ sizeof(CARD32), False, AnyPropertyType,
+ &atomReturnType, &iReturnFormat,
+ &ulReturnItems, &ulReturnBytesLeft,
+ &pszReturnData);
+
+ fprintf(stderr, "Name: ");
+
+ if (result == Success && pszReturnData != NULL)
+ {
+ pszReturnData[ulReturnItems] = '\0';
+
+ fprintf(stderr, "\"%s\"\n", (char *) pszReturnData);
+ }
+ else
+ {
+ fprintf(stderr, "%s\n", "( has no name )");
+ }
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ fprintf(stderr, "x=%d y=%d width=%d height=%d class=%s map_state=%s "
+ "override_redirect=%s", pWin -> drawable.x, pWin -> drawable.y,
+ pWin -> drawable.width, pWin -> drawable.height,
+ (pWin -> drawable.class == 0) ? "CopyFromParent" :
+ ((pWin -> drawable.class == 1) ? "InputOutput" :
+ "InputOnly"),
+ (pWin -> mapped == 0) ?
+ "IsUnmapped" : (pWin -> realized == 0 ?
+ "IsUnviewable" : "IsViewable"),
+ (pWin -> overrideRedirect == 0) ?
+ "No" : "Yes");
+
+ if (newLine == TRUE)
+ {
+ fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * Walk internal windows tree.
+ */
+
+void nxagentInternalWindowsTree(WindowPtr pWin, int indent)
+{
+ WindowPtr pChild;
+ int i;
+
+ while (pWin)
+ {
+ pChild = pWin -> firstChild;
+
+ for (i = 0; i < indent; i++)
+ {
+ fprintf(stderr, " ");
+ }
+
+ nxagentInternalWindowInfo(pWin, indent, TRUE);
+
+ fprintf(stderr, "\n");
+
+ nxagentInternalWindowsTree(pChild, indent + 4);
+
+ pWin = pWin -> nextSib;
+ }
+}
+
+#endif /* DEBUG_TREE */
+
+void nxagentSwitchResizeMode(ScreenPtr pScreen)
+{
+ XSizeHints sizeHints;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSwitchResizeMode called.\n");
+ #endif
+
+ int desktopResize = nxagentOption(DesktopResize);
+
+ nxagentChangeOption(DesktopResize, !desktopResize);
+
+ sizeHints.flags = PMaxSize;
+
+ if (nxagentOption(DesktopResize) == 0)
+ {
+ fprintf(stderr,"Info: Disabled desktop resize mode in agent.\n");
+
+ nxagentLaunchDialog(DIALOG_DISABLE_DESKTOP_RESIZE_MODE);
+
+ if (nxagentOption(Fullscreen) == 0)
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &sizeHints);
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Info: Enabled desktop resize mode in agent.\n");
+
+ nxagentLaunchDialog(DIALOG_ENABLE_DESKTOP_RESIZE_MODE);
+
+ nxagentChangeScreenConfig(0, nxagentOption(Width), nxagentOption(Height),
+ 0, 0);
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt)
+ {
+ NXSetExposeParameters(nxagentDisplay, 0, 0, 0);
+ }
+
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &sizeHints);
+ }
+}
+
+void nxagentShadowSwitchResizeMode(ScreenPtr pScreen)
+{
+ XSizeHints sizeHints;
+
+ int desktopResize = nxagentOption(DesktopResize);
+
+ nxagentChangeOption(DesktopResize, !desktopResize);
+
+ sizeHints.flags = PMaxSize;
+
+ if (nxagentOption(DesktopResize) == 0)
+ {
+ nxagentShadowSetRatio(1.0, 1.0);
+
+ nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)], screenInfo.screens[0]->root,
+ screenInfo.screens[0]->root -> drawable.width, screenInfo.screens[0]->root -> drawable.height);
+
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+
+ fprintf(stderr,"Info: Disabled resize mode in shadow agent.\n");
+ }
+ else
+ {
+ nxagentShadowSetRatio(nxagentOption(Width) * 1.0 /
+ screenInfo.screens[0]->root -> drawable.width,
+ nxagentOption(Height) * 1.0 /
+ screenInfo.screens[0]->root -> drawable.height);
+
+ nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)],
+ screenInfo.screens[0]->root, screenInfo.screens[0]->root -> drawable.width,
+ screenInfo.screens[0]->root -> drawable.height);
+
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+
+ fprintf(stderr,"Info: Enabled resize mode in shadow agent.\n");
+ }
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum],
+ &sizeHints);
+}
+
+static void nxagentSwitchDeferMode(void)
+{
+ if (nxagentOption(DeferLevel) == 0)
+ {
+ nxagentChangeOption(DeferLevel, UNDEFINED);
+
+ nxagentSetDeferLevel();
+ }
+ else
+ {
+ nxagentChangeOption(DeferLevel, 0);
+ }
+
+ if (nxagentOption(DeferLevel) != 0)
+ {
+ nxagentLaunchDialog(DIALOG_ENABLE_DEFER_MODE);
+ }
+ else
+ {
+ nxagentLaunchDialog(DIALOG_DISABLE_DEFER_MODE);
+
+ nxagentForceSynchronization = 1;
+ }
+}
+
+static Bool nxagentExposurePredicate(Display *display, XEvent *event, XPointer window)
+{
+ /*
+ * Handle both Expose and ProcessedExpose events.
+ * The latters are those not filtered by function
+ * nxagentWindowExposures().
+ */
+
+ if (window)
+ {
+ return ((event -> type == Expose || event -> type == ProcessedExpose) &&
+ event -> xexpose.window == *((Window *) window));
+ }
+ else
+ {
+ return (event -> type == Expose || event -> type == ProcessedExpose);
+ }
+}
+
+static int nxagentAnyEventPredicate(Display *display, XEvent *event, XPointer parameter)
+{
+ return 1;
+}
+
+int nxagentInputEventPredicate(Display *display, XEvent *event, XPointer parameter)
+{
+ switch (event -> type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease:
+ {
+ return 1;
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+void nxagentInitDefaultEventMask()
+{
+ Mask mask = NoEventMask;
+
+ mask |= (StructureNotifyMask | VisibilityChangeMask);
+
+ mask |= ExposureMask;
+
+ mask |= NXAGENT_KEYBOARD_EVENT_MASK;
+ mask |= NXAGENT_POINTER_EVENT_MASK;
+
+ defaultEventMask = mask;
+}
+
+void nxagentGetDefaultEventMask(Mask *mask_return)
+{
+ *mask_return = defaultEventMask;
+}
+
+void nxagentSetDefaultEventMask(Mask mask)
+{
+ defaultEventMask = mask;
+}
+
+void nxagentGetEventMask(WindowPtr pWin, Mask *mask_return)
+{
+ Mask mask = NoEventMask;
+
+ if (nxagentOption(Rootless))
+ {
+ /*
+ * mask = pWin -> eventMask &
+ * ~(NXAGENT_KEYBOARD_EVENT_MASK | NXAGENT_POINTER_EVENT_MASK);
+ */
+
+ if (pWin -> drawable.class == InputOutput)
+ {
+ if (nxagentWindowTopLevel(pWin))
+ {
+ mask = defaultEventMask;
+ }
+ else
+ {
+ mask = ExposureMask | VisibilityChangeMask | PointerMotionMask;
+ }
+ }
+
+ mask |= PropertyChangeMask;
+ }
+ else if (pWin -> drawable.class != InputOnly)
+ {
+ mask = ExposureMask | VisibilityChangeMask;
+ }
+
+ *mask_return = mask;
+}
+
+static int nxagentChangeMapPrivate(WindowPtr pWin, void * ptr)
+{
+ if (pWin && nxagentWindowPriv(pWin))
+ {
+ nxagentWindowPriv(pWin) -> isMapped = *((Bool *) ptr);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+static int nxagentChangeVisibilityPrivate(WindowPtr pWin, void * ptr)
+{
+ if (pWin && nxagentWindowPriv(pWin))
+ {
+ nxagentWindowPriv(pWin) -> visibilityState = *((int *) ptr);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+void nxagentDispatchEvents(PredicateFuncPtr predicate)
+{
+ XEvent X;
+ xEvent x;
+ ScreenPtr pScreen = NULL;
+
+ Bool minimize = False;
+ Bool startKbd = False;
+ Bool closeSession = False;
+ Bool switchFullscreen = False;
+ Bool switchAllScreens = False;
+
+ /*
+ * Last entered top level window.
+ */
+
+ static WindowPtr nxagentLastEnteredTopLevelWindow = NULL;
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin read]\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new events with "
+ "predicate [%p].\n", predicate);
+ #endif
+
+ if (nxagentRemoteExposeRegion == NULL)
+ {
+ nxagentInitRemoteExposeRegion();
+ }
+
+ /*
+ * We must read here, even if apparently there is
+ * nothing to read. The ioctl() based readable
+ * function, in fact, is often unable to detect a
+ * failure of the socket, in particular if the
+ * agent was connected to the proxy and the proxy
+ * is gone. Thus we must trust the wakeup handler
+ * that called us after the select().
+ */
+
+ #ifdef TEST
+
+ if (nxagentPendingEvents(nxagentDisplay) == 0)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: PANIC! No event needs to be dispatched.\n");
+ }
+
+ #endif
+
+ /*
+ * We want to process all the events already in
+ * the queue, plus any additional event that may
+ * be read from the network. If no event can be
+ * read, we want to continue handling our clients
+ * without flushing the output buffer.
+ */
+
+ while (nxagentCheckEvents(nxagentDisplay, &X, predicate != NULL ? predicate :
+ nxagentAnyEventPredicate, NULL) == 1)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new event type [%d].\n",
+ X.type);
+ #endif
+
+ /*
+ * Handle the incoming event.
+ */
+
+ switch (X.type)
+ {
+ #ifdef NXAGENT_CLIPBOARD
+
+ case SelectionClear:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionClear event.\n");
+ #endif
+
+ nxagentClearSelection(&X);
+
+ break;
+ }
+ case SelectionRequest:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionRequest event.\n");
+ #endif
+
+ nxagentRequestSelection(&X);
+
+ break;
+ }
+ case SelectionNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new SelectionNotify event.\n");
+ #endif
+
+ nxagentNotifySelection(&X);
+
+ break;
+ }
+
+ #endif /* NXAGENT_CLIPBOARD */
+
+ case PropertyNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: PropertyNotify on "
+ "prop %d[%s] window %lx state %d\n",
+ (int)X.xproperty.atom, validateString(XGetAtomName(nxagentDisplay, X.xproperty.atom)),
+ X.xproperty.window, X.xproperty.state);
+ #endif
+
+ nxagentHandlePropertyNotify(&X);
+
+ break;
+ }
+ case KeyPress:
+ {
+ enum HandleEventResult result;
+
+ KeySym keysym;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeyPress event.\n");
+ #endif
+
+ nxagentInputEvent = 1;
+
+ nxagentKeyDown++;
+
+ nxagentHandleKeyPress(&X, &result);
+
+ if (viewportLastKeyPressResult != result)
+ {
+ viewportInc = 1;
+
+ viewportLastKeyPressResult = result;
+ }
+
+ if (result != doNothing && result != doStartKbd)
+ {
+ pScreen = nxagentScreen(X.xkey.window);
+ }
+
+ switch (result)
+ {
+ case doNothing:
+ {
+ break;
+ }
+
+ #ifdef DEBUG_TREE
+
+ case doDebugTree:
+ {
+ fprintf(stderr, "\n ========== nxagentRemoteWindowsTree ==========\n");
+ nxagentRemoteWindowsTree(nxagentWindow(screenInfo.screens[0]->root), 0);
+
+ fprintf(stderr, "\n========== nxagentInternalWindowsTree ==========\n");
+ nxagentInternalWindowsTree(screenInfo.screens[0]->root, 0);
+
+ break;
+ }
+
+ #endif /* DEBUG_TREE */
+
+ case doCloseSession:
+ {
+ closeSession = TRUE;
+
+ break;
+ }
+ case doMinimize:
+ {
+ minimize = TRUE;
+
+ break;
+ }
+ case doStartKbd:
+ {
+ startKbd = TRUE;
+
+ break;
+ }
+ case doSwitchFullscreen:
+ {
+ switchFullscreen = TRUE;
+
+ break;
+ }
+ case doSwitchAllScreens:
+ {
+ switchAllScreens = TRUE;
+
+ break;
+ }
+ case doViewportMoveUp:
+ {
+ nxagentMoveViewport(pScreen, 0, -nxagentOption(Height));
+
+ break;
+ }
+ case doViewportMoveDown:
+ {
+ nxagentMoveViewport(pScreen, 0, nxagentOption(Height));
+
+ break;
+ }
+ case doViewportMoveLeft:
+ {
+ nxagentMoveViewport(pScreen, -nxagentOption(Width), 0);
+
+ break;
+ }
+ case doViewportMoveRight:
+ {
+ nxagentMoveViewport(pScreen, nxagentOption(Width), 0);
+
+ break;
+ }
+ case doViewportUp:
+ {
+ nxagentMoveViewport(pScreen, 0, -nextinc(viewportInc));
+
+ break;
+ }
+ case doViewportDown:
+ {
+ nxagentMoveViewport(pScreen, 0, +nextinc(viewportInc));
+
+ break;
+ }
+ case doViewportLeft:
+ {
+ nxagentMoveViewport(pScreen, -nextinc(viewportInc), 0);
+
+ break;
+ }
+ case doViewportRight:
+ {
+ nxagentMoveViewport(pScreen, +nextinc(viewportInc), 0);
+
+ break;
+ }
+ case doSwitchResizeMode:
+ {
+ if (nxagentOption(Shadow) == 0)
+ {
+ if (nxagentNoDialogIsRunning)
+ {
+ nxagentSwitchResizeMode(pScreen);
+ }
+ }
+ else
+ {
+ nxagentShadowSwitchResizeMode(pScreen);
+ }
+
+ break;
+ }
+ case doSwitchDeferMode:
+ {
+ if (nxagentNoDialogIsRunning)
+ {
+ nxagentSwitchDeferMode();
+ }
+
+ break;
+ }
+ default:
+ {
+ FatalError("nxagentDispatchEvent: handleKeyPress returned unknown value\n");
+
+ break;
+ }
+ }
+
+ /*
+ * Elide multiple KeyPress/KeyRelease events of
+ * the same key and generate a single pair. This
+ * is intended to reduce the impact of the laten-
+ * cy on the key auto-repeat, handled by the re-
+ * mote X server. We may optionally do that only
+ * if the timestamps in the events show an exces-
+ * sive delay.
+ */
+
+ keysym = XKeycodeToKeysym(nxagentDisplay, X.xkey.keycode, 0);
+
+ if (nxagentMonitoredDuplicate(keysym) == 1)
+ {
+ nxagentRemoveDuplicatedKeys(&X);
+ }
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow) == 1 && result == doNothing)
+ {
+ X.xkey.keycode = nxagentConvertKeycode(X.xkey.keycode);
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+
+ break;
+ }
+ case KeyRelease:
+ {
+ enum HandleEventResult result;
+ int sendKey = 0;
+
+/*
+FIXME: If we don't flush the queue here, it could happen
+ that the inputInfo structure will not be up to date
+ when we perform the following check on down keys.
+*/
+ ProcessInputEvents();
+
+/*
+FIXME: Don't enqueue the KeyRelease event if the key was
+ not already pressed. This workaround avoids a fake
+ KeyPress is enqueued by the XKEYBOARD extension.
+ Another solution would be to let the events are
+ enqueued and to remove the KeyPress afterwards.
+*/
+ if (BitIsOn(inputInfo.keyboard -> key -> down,
+ nxagentConvertKeycode(X.xkey.keycode)))
+ {
+ sendKey = 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeyRelease event.\n");
+ #endif
+
+ nxagentInputEvent = 1;
+
+ nxagentKeyDown--;
+
+ if (nxagentKeyDown <= 0)
+ {
+ nxagentKeyDown = 0;
+ }
+
+ if (nxagentXkbState.Initialized == 0)
+ {
+ if (X.xkey.keycode == nxagentCapsLockKeycode)
+ {
+ nxagentXkbCapsTrap = 1;
+ }
+ else if (X.xkey.keycode == nxagentNumLockKeycode)
+ {
+ nxagentXkbNumTrap = 1;
+ }
+
+ nxagentInitKeyboardState();
+
+ nxagentXkbCapsTrap = 0;
+ nxagentXkbNumTrap = 0;
+ }
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = KeyRelease;
+ x.u.u.detail = nxagentConvertKeycode(X.xkey.keycode);
+ x.u.keyButtonPointer.time = nxagentLastKeyPressTime +
+ (X.xkey.time - nxagentLastServerTime);
+
+ nxagentLastServerTime = X.xkey.time;
+
+ nxagentLastEventTime = GetTimeInMillis();
+
+ if (x.u.keyButtonPointer.time > nxagentLastEventTime)
+ {
+ x.u.keyButtonPointer.time = nxagentLastEventTime;
+ }
+
+ if (!(nxagentCheckSpecialKeystroke(&X.xkey, &result)) && sendKey == 1)
+ {
+ mieqEnqueue(&x);
+
+ CriticalOutputPending = 1;
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow))
+ {
+ X.xkey.keycode = nxagentConvertKeycode(X.xkey.keycode);
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+ }
+
+ break;
+ }
+ case ButtonPress:
+ {
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new ButtonPress event.\n");
+ }
+ #endif
+
+ nxagentInputEvent = 1;
+
+ if (nxagentOption(Fullscreen))
+ {
+ if (nxagentMagicPixelZone(X.xbutton.x, X.xbutton.y))
+ {
+ pScreen = nxagentScreen(X.xbutton.window);
+
+ minimize = True;
+
+ break;
+ }
+ }
+
+ if (nxagentIpaq && nxagentClients <= 0)
+ {
+ closeSession = TRUE;
+ }
+
+ if (nxagentOption(DesktopResize) == False &&
+ (X.xbutton.state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask))
+ {
+ /*
+ * Start viewport navigation mode.
+ */
+
+ int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource,
+ nxagentCollectGrabPointerPredicate);
+
+ ScreenPtr pScreen = nxagentScreen(X.xbutton.window);
+ viewportCursor = XCreateFontCursor(nxagentDisplay, XC_fleur);
+
+ NXCollectGrabPointer(nxagentDisplay, resource,
+ nxagentDefaultWindows[pScreen -> myNum], True,
+ NXAGENT_POINTER_EVENT_MASK, GrabModeAsync,
+ GrabModeAsync, None, viewportCursor,
+ CurrentTime);
+ viewportLastX = X.xbutton.x;
+ viewportLastY = X.xbutton.y;
+
+ break;
+ }
+
+ if (!(nxagentOption(Fullscreen) &&
+ X.xbutton.window == nxagentFullscreenWindow &&
+ X.xbutton.subwindow == None))
+ {
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = ButtonPress;
+ x.u.u.detail = inputInfo.pointer -> button -> map[nxagentReversePointerMap[X.xbutton.button]];
+ x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+
+ if (nxagentOption(Rootless))
+ {
+ x.u.keyButtonPointer.rootX = X.xmotion.x_root;
+ x.u.keyButtonPointer.rootY = X.xmotion.y_root;
+ }
+ else
+ {
+ x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX);
+ x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY);
+ }
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding ButtonPress event.\n");
+ }
+ #endif
+
+ mieqEnqueue(&x);
+
+ CriticalOutputPending = 1;
+ }
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow))
+ {
+ X.xbutton.x -= nxagentOption(RootX);
+ X.xbutton.y -= nxagentOption(RootY);
+
+ if (nxagentOption(YRatio) != DONT_SCALE)
+ {
+ X.xbutton.x = (X.xbutton.x << PRECISION) / nxagentOption(YRatio);
+ }
+
+ if (nxagentOption(XRatio) != DONT_SCALE)
+ {
+ X.xbutton.y = (X.xbutton.y << PRECISION) / nxagentOption(YRatio);
+ }
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+
+ break;
+ }
+ case ButtonRelease:
+ {
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new ButtonRelease event.\n");
+ }
+ #endif
+
+ nxagentInputEvent = 1;
+
+ if (viewportCursor)
+ {
+ /*
+ * Leave viewport navigation mode.
+ */
+
+ XUngrabPointer(nxagentDisplay, CurrentTime);
+
+ XFreeCursor(nxagentDisplay, viewportCursor);
+
+ viewportCursor = None;
+ }
+
+ if (minimize != True)
+ {
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = ButtonRelease;
+ x.u.u.detail = inputInfo.pointer -> button -> map[nxagentReversePointerMap[X.xbutton.button]];
+ x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+
+ if (nxagentOption(Rootless))
+ {
+ x.u.keyButtonPointer.rootX = X.xmotion.x_root;
+ x.u.keyButtonPointer.rootY = X.xmotion.y_root;
+ }
+ else
+ {
+ x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX);
+ x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY);
+ }
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding ButtonRelease event.\n");
+ }
+ #endif
+
+ mieqEnqueue(&x);
+
+ CriticalOutputPending = 1;
+ }
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow))
+ {
+ X.xbutton.x -= nxagentOption(RootX);
+ X.xbutton.y -= nxagentOption(RootY);
+
+ if (nxagentOption(XRatio) != DONT_SCALE)
+ {
+ X.xbutton.x = (X.xbutton.x << PRECISION) / nxagentOption(XRatio);
+ }
+
+ if (nxagentOption(YRatio) != DONT_SCALE)
+ {
+ X.xbutton.y = (X.xbutton.y << PRECISION) / nxagentOption(YRatio);
+ }
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+
+ break;
+ }
+ case MotionNotify:
+ {
+ ScreenPtr pScreen = nxagentScreen(X.xmotion.window);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new MotionNotify event.\n");
+ #endif
+
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Handling motion notify window [%ld] root [%ld] child [%ld].\n",
+ X.xmotion.window, X.xmotion.root, X.xmotion.subwindow);
+
+ fprintf(stderr, "nxagentDispatchEvents: Pointer at [%d][%d] relative root [%d][%d].\n",
+ X.xmotion.x, X.xmotion.y, X.xmotion.x_root, X.xmotion.y_root);
+ }
+ #endif
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = MotionNotify;
+
+ if (nxagentOption(Rootless))
+ {
+ WindowPtr pWin = nxagentWindowPtr(X.xmotion.window);
+
+ if (pWin)
+ {
+ nxagentLastEnteredWindow = pWin;
+ }
+
+ if (nxagentPulldownDialogPid == 0 && nxagentLastEnteredTopLevelWindow &&
+ (X.xmotion.y_root < nxagentLastEnteredTopLevelWindow -> drawable.y + 4))
+ {
+ if (pWin && nxagentClientIsDialog(wClient(pWin)) == 0 &&
+ nxagentLastEnteredTopLevelWindow -> parent == screenInfo.screens[0]->root &&
+ nxagentLastEnteredTopLevelWindow -> overrideRedirect == False &&
+ X.xmotion.x_root > (nxagentLastEnteredTopLevelWindow -> drawable.x +
+ (nxagentLastEnteredTopLevelWindow -> drawable.width >> 1) - 50) &&
+ X.xmotion.x_root < (nxagentLastEnteredTopLevelWindow -> drawable.x +
+ (nxagentLastEnteredTopLevelWindow -> drawable.width >> 1) + 50) &&
+ nxagentOption(Menu) == 1)
+ {
+ nxagentPulldownDialog(nxagentLastEnteredTopLevelWindow -> drawable.id);
+ }
+ }
+
+ x.u.keyButtonPointer.rootX = X.xmotion.x_root;
+ x.u.keyButtonPointer.rootY = X.xmotion.y_root;
+ }
+ else
+ {
+ x.u.keyButtonPointer.rootX = X.xmotion.x - nxagentOption(RootX);
+ x.u.keyButtonPointer.rootY = X.xmotion.y - nxagentOption(RootY);
+ }
+
+ x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+
+ if (viewportCursor == None &&
+ !(nxagentOption(Fullscreen) &&
+ X.xmotion.window == nxagentDefaultWindows[pScreen -> myNum]
+ && X.xmotion.subwindow == None))
+ {
+ #ifdef NX_DEBUG_INPUT
+ if (nxagentDebugInput == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Adding motion event [%d, %d] to the queue.\n",
+ x.u.keyButtonPointer.rootX, x.u.keyButtonPointer.rootY);
+ }
+ #endif
+
+ mieqEnqueue(&x);
+ }
+
+ /*
+ * This test is more complicated and probably not necessary, compared
+ * to a simple check on viewportCursor.
+ *
+ * if (!nxagentOption(Fullscreen) &&
+ * (X.xmotion.state & (ControlMask | Mod1Mask | Button1Mask)) ==
+ * (ControlMask | Mod1Mask | Button1Mask))
+ */
+
+ if (viewportCursor)
+ {
+ /*
+ * Pointer is in viewport navigation mode.
+ */
+
+ nxagentMoveViewport(pScreen, viewportLastX - X.xmotion.x, viewportLastY - X.xmotion.y);
+
+ viewportLastX = X.xmotion.x;
+ viewportLastY = X.xmotion.y;
+ }
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow) && !viewportCursor)
+ {
+ X.xmotion.x -= nxagentOption(RootX);
+ X.xmotion.y -= nxagentOption(RootY);
+
+ if (nxagentOption(XRatio) != DONT_SCALE)
+ {
+ X.xmotion.x = (X.xmotion.x << PRECISION) / nxagentOption(XRatio);
+ }
+
+ if (nxagentOption(YRatio) != DONT_SCALE)
+ {
+ X.xmotion.y = (X.xmotion.y << PRECISION) / nxagentOption(YRatio);
+ }
+
+ NXShadowEvent(nxagentDisplay, X);
+ }
+
+ if (nxagentOption(Shadow) == 0)
+ {
+ nxagentInputEvent = 1;
+ }
+
+ break;
+ }
+ case FocusIn:
+ {
+ WindowPtr pWin;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusIn event.\n");
+ #endif
+
+ /*
+ * Here we change the focus state in the agent.
+ * It looks like this is needed only for root-
+ * less mode at the present moment.
+ */
+
+ if (nxagentOption(Rootless) &&
+ (pWin = nxagentWindowPtr(X.xfocus.window)))
+ {
+ SetInputFocus(serverClient, inputInfo.keyboard, pWin -> drawable.id,
+ RevertToPointerRoot, GetTimeInMillis(), False);
+ }
+
+ if (X.xfocus.detail != NotifyInferior)
+ {
+ pScreen = nxagentScreen(X.xfocus.window);
+
+ if (pScreen)
+ {
+ nxagentDirectInstallColormaps(pScreen);
+ }
+ }
+
+ break;
+ }
+ case FocusOut:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new FocusOut event.\n");
+ #endif
+
+ if (X.xfocus.detail != NotifyInferior)
+ {
+ pScreen = nxagentScreen(X.xfocus.window);
+
+ if (pScreen)
+ {
+ nxagentDirectUninstallColormaps(pScreen);
+ }
+ }
+
+ #ifdef NXAGENT_FIXKEYS
+
+ {
+ /*
+ * Force the keys all up when focus is lost.
+ */
+
+ int i, k;
+ int mask = 1;
+ CARD8 val;
+
+ XEvent xM;
+ memset(&xM, 0, sizeof(XEvent));
+
+ for (i = 0; i < DOWN_LENGTH; i++) /* input.h */
+ {
+ val = inputInfo.keyboard->key->down[i];
+
+ if (val != 0)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ if (val & (mask << k))
+ {
+ #ifdef NXAGENT_FIXKEYS_DEBUG
+ fprintf(stderr, "sending KeyRelease event for keycode: %x\n",
+ i * 8 + k);
+ #endif
+
+ if (!nxagentOption(Rootless) ||
+ inputInfo.keyboard->key->modifierMap[i * 8 + k])
+ {
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = KeyRelease;
+ x.u.u.detail = i * 8 + k;
+ x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+
+ if (nxagentOption(ViewOnly) == 0 && nxagentOption(Shadow))
+ {
+ xM.type = KeyRelease;
+ xM.xkey.display = nxagentDisplay;
+ xM.xkey.type = KeyRelease;
+ xM.xkey.keycode = i * 8 + k;
+ xM.xkey.state = inputInfo.keyboard->key->state;
+ xM.xkey.time = GetTimeInMillis();
+ NXShadowEvent(nxagentDisplay, xM);
+ }
+
+ mieqEnqueue(&x);
+ }
+ }
+ }
+ }
+ }
+
+ nxagentKeyDown = 0;
+ }
+
+ #endif /* NXAGENT_FIXKEYS */
+
+ break;
+ }
+ case KeymapNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new KeymapNotify event.\n");
+ #endif
+
+ break;
+ }
+ case EnterNotify:
+ {
+ WindowPtr pWin;
+
+ WindowPtr pTLWin = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new EnterNotify event.\n");
+ #endif
+
+ if (nxagentOption(Rootless))
+ {
+ pWin = nxagentWindowPtr(X.xcrossing.window);
+
+ if (pWin != NULL)
+ {
+ for (pTLWin = pWin;
+ pTLWin -> parent != pTLWin -> drawable.pScreen -> root;
+ pTLWin = pTLWin -> parent);
+ }
+
+ if (pTLWin)
+ {
+ nxagentLastEnteredTopLevelWindow = pTLWin;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: nxagentLastEnteredTopLevelWindow [%p].\n",
+ nxagentLastEnteredTopLevelWindow);
+ #endif
+ }
+
+ if (nxagentOption(Rootless) && nxagentWMIsRunning &&
+ (pWin = nxagentWindowPtr(X.xcrossing.window)) &&
+ nxagentWindowTopLevel(pWin) && !pWin -> overrideRedirect &&
+ (pWin -> drawable.x != X.xcrossing.x_root - X.xcrossing.x - pWin -> borderWidth ||
+ pWin -> drawable.y != X.xcrossing.y_root - X.xcrossing.y - pWin -> borderWidth))
+ {
+ /*
+ * This code is useful for finding the window
+ * position. It should be re-implemented by
+ * following the ICCCM 4.1.5 recommendations.
+ */
+
+ XID values[4];
+ register XID *value = values;
+ Mask mask = 0;
+ ClientPtr pClient = wClient(pWin);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: pWin -> drawable.x [%d] pWin -> drawable.y [%d].\n",
+ pWin -> drawable.x, pWin -> drawable.y);
+ #endif
+
+ *value++ = (XID) (X.xcrossing.x_root - X.xcrossing.x - pWin -> borderWidth);
+ *value++ = (XID) (X.xcrossing.y_root - X.xcrossing.y - pWin -> borderWidth);
+
+ /*
+ * nxagentWindowPriv(pWin)->x = (X.xcrossing.x_root - X.xcrossing.x);
+ * nxagentWindowPriv(pWin)->y = (X.xcrossing.y_root - X.xcrossing.y);
+ */
+
+ mask = CWX | CWY;
+
+ nxagentScreenTrap = 1;
+
+ ConfigureWindow(pWin, mask, (XID *) values, pClient);
+
+ nxagentScreenTrap = 0;
+ }
+
+ if (nxagentOption(Fullscreen) == 1 &&
+ X.xcrossing.window == nxagentFullscreenWindow &&
+ X.xcrossing.detail != NotifyInferior)
+ {
+ nxagentGrabPointerAndKeyboard(&X);
+ }
+
+ if (X.xcrossing.detail != NotifyInferior)
+ {
+ pScreen = nxagentScreen(X.xcrossing.window);
+
+ if (pScreen)
+ {
+ NewCurrentScreen(pScreen, X.xcrossing.x, X.xcrossing.y);
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = MotionNotify;
+
+ if (nxagentOption(Rootless))
+ {
+ nxagentLastEnteredWindow = nxagentWindowPtr(X.xcrossing.window);
+ x.u.keyButtonPointer.rootX = X.xcrossing.x_root;
+ x.u.keyButtonPointer.rootY = X.xcrossing.y_root;
+ }
+ else
+ {
+ x.u.keyButtonPointer.rootX = X.xcrossing.x - nxagentOption(RootX);
+ x.u.keyButtonPointer.rootY = X.xcrossing.y - nxagentOption(RootY);
+ }
+
+ x.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+
+ mieqEnqueue(&x);
+
+ nxagentDirectInstallColormaps(pScreen);
+ }
+ }
+
+ nxagentInputEvent = 1;
+
+ break;
+ }
+ case LeaveNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new LeaveNotify event.\n");
+ #endif
+
+ if (nxagentOption(Rootless) && X.xcrossing.mode == NotifyNormal &&
+ X.xcrossing.detail != NotifyInferior)
+ {
+ nxagentLastEnteredWindow = NULL;
+ }
+
+ if (X.xcrossing.window == nxagentDefaultWindows[0] &&
+ X.xcrossing.detail != NotifyInferior &&
+ X.xcrossing.mode == NotifyNormal)
+ {
+ nxagentUngrabPointerAndKeyboard(&X);
+ }
+
+ if (X.xcrossing.detail != NotifyInferior)
+ {
+ pScreen = nxagentScreen(X.xcrossing.window);
+
+ if (pScreen)
+ {
+ nxagentDirectUninstallColormaps(pScreen);
+ }
+ }
+
+ nxagentInputEvent = 1;
+
+ break;
+ }
+ case DestroyNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new DestroyNotify event.\n");
+ #endif
+
+ if (nxagentParentWindow != (Window) 0 &&
+ X.xdestroywindow.window == nxagentParentWindow)
+ {
+ fprintf(stderr, "Warning: Unhandled destroy notify event received in agent.\n");
+ }
+
+ break;
+ }
+ case ClientMessage:
+ {
+ enum HandleEventResult result;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new ClientMessage event.\n");
+ #endif
+
+ nxagentHandleClientMessageEvent(&X, &result);
+
+ if (result == doCloseSession)
+ {
+ closeSession = TRUE;
+ }
+
+ break;
+ }
+ case VisibilityNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new VisibilityNotify event.\n");
+ #endif
+
+ if (X.xvisibility.window != nxagentDefaultWindows[0])
+ {
+ Window window = X.xvisibility.window;
+
+ WindowPtr pWin = nxagentWindowPtr(window);
+
+ if (pWin && nxagentWindowPriv(pWin))
+ {
+ if (nxagentWindowPriv(pWin) -> visibilityState != X.xvisibility.state)
+ {
+ int value = X.xvisibility.state;
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ TraverseTree(pWin, nxagentChangeVisibilityPrivate, &value);
+ }
+ else
+ {
+ nxagentChangeVisibilityPrivate(pWin, &value);
+ }
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Suppressing visibility notify on window [%lx].\n",
+ X.xvisibility.window);
+ #endif
+
+ break;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Visibility notify state is [%d] with previous [%d].\n",
+ X.xvisibility.state, nxagentVisibility);
+ #endif
+
+ nxagentVisibility = X.xvisibility.state;
+
+ break;
+ }
+ case Expose:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new Expose event.\n");
+
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Received Expose event "
+ "for drawable [%lx] geometry [%d, %d, %d, %d] count [%d].\n",
+ X.xexpose.window, X.xexpose.x, X.xexpose.y, X.xexpose.width,
+ X.xexpose.height, X.xexpose.count);
+ #endif
+
+ nxagentHandleExposeEvent(&X);
+
+ break;
+ }
+ case GraphicsExpose:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new GraphicsExpose event.\n");
+
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Received GraphicsExpose event "
+ "for drawable [%lx] geometry [%d, %d, %d, %d] count [%d].\n",
+ X.xgraphicsexpose.drawable, X.xgraphicsexpose.x, X.xgraphicsexpose.y,
+ X.xgraphicsexpose.width, X.xgraphicsexpose.height,
+ X.xgraphicsexpose.count);
+ #endif
+
+ nxagentHandleGraphicsExposeEvent(&X);
+
+ break;
+ }
+ case NoExpose:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new NoExpose event.\n");
+
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Received NoExpose event for "
+ "drawable [%lx].\n", X.xnoexpose.drawable);
+ #endif
+
+ break;
+ }
+ case CirculateNotify:
+ {
+ /*
+ * WindowPtr pWin;
+ * WindowPtr pSib;
+ * ClientPtr pClient;
+
+ * XID values[2];
+ * register XID *value = values;
+ * Mask mask = 0;
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new CirculateNotify event.\n");
+ #endif
+
+ /*
+ * FIXME: Do we need this?
+ *
+ * pWin = nxagentWindowPtr(X.xcirculate.window);
+ *
+ * if (!pWin)
+ * {
+ * pWin = nxagentRootlessTopLevelWindow(X.xcirculate.window);
+ * }
+ *
+ * if (!pWin)
+ * {
+ * break;
+ * }
+ *
+ * XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ * &root_return, &parent_return, &children_return, &nchildren_return);
+ *
+ * nxagentRootlessRestack(children_return, nchildren_return);
+ */
+
+ break;
+ }
+ case ConfigureNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new ConfigureNotify event.\n");
+ #endif
+
+ if (nxagentConfiguredSynchroWindow == X.xconfigure.window)
+ {
+ if (nxagentExposeQueue.exposures[nxagentExposeQueue.start].serial != X.xconfigure.x)
+ {
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: Requested ConfigureNotify changes didn't take place.\n");
+ }
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Received ConfigureNotify and going to call "
+ "nxagentSynchronizeExpose.\n");
+ #endif
+
+ nxagentSynchronizeExpose();
+
+ break;
+ }
+
+ nxagentHandleConfigureNotify(&X);
+
+ break;
+ }
+ case GravityNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new GravityNotify event.\n");
+ #endif
+
+ break;
+ }
+ case ReparentNotify:
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new ReparentNotify event.\n");
+ #endif
+
+ nxagentHandleReparentNotify(&X);
+
+ break;
+ }
+ case UnmapNotify:
+ {
+ WindowPtr pWin;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new UnmapNotify event.\n");
+ #endif
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ if ((pWin = nxagentRootlessTopLevelWindow(X.xunmap.window)) != NULL ||
+ ((pWin = nxagentWindowPtr(X.xunmap.window)) != NULL &&
+ nxagentWindowTopLevel(pWin) == 1))
+ {
+ nxagentScreenTrap = 1;
+
+ UnmapWindow(pWin, False);
+
+ nxagentScreenTrap = 0;
+ }
+ }
+
+ if (nxagentUseNXTrans == 1 && nxagentOption(Rootless) == 0 &&
+ nxagentOption(Nested) == 0 &&
+ X.xmap.window != nxagentIconWindow)
+ {
+ nxagentVisibility = VisibilityFullyObscured;
+ }
+
+ break;
+ }
+ case MapNotify:
+ {
+ WindowPtr pWin;
+ ClientPtr pClient;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Going to handle new MapNotify event.\n");
+ #endif
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ Bool value = 1;
+
+ if ((pWin = nxagentRootlessTopLevelWindow(X.xmap.window)) != NULL ||
+ ((pWin = nxagentWindowPtr(X.xmap.window)) != NULL &&
+ nxagentWindowTopLevel(pWin) == 1))
+ {
+ pClient = wClient(pWin);
+
+ nxagentScreenTrap = 1;
+
+ MapWindow(pWin, pClient);
+
+ nxagentScreenTrap = 0;
+ }
+
+ if (pWin != NULL)
+ {
+ TraverseTree(pWin, nxagentChangeMapPrivate, &value);
+ }
+ }
+
+ if (nxagentOption(AllScreens) == 1)
+ {
+ if (X.xmap.window == nxagentIconWindow)
+ {
+ pScreen = nxagentScreen(X.xmap.window);
+ nxagentMaximizeToFullScreen(pScreen);
+ }
+ }
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ nxagentVisibility = VisibilityUnobscured;
+ nxagentVisibilityStop = False;
+ nxagentVisibilityTimeout = GetTimeInMillis() + 2000;
+ }
+
+ break;
+ }
+ case MappingNotify:
+ {
+ XMappingEvent *mappingEvent = (XMappingEvent *) &X;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Going to handle new MappingNotify event.\n");
+ #endif
+
+ if (mappingEvent -> request == MappingPointer)
+ {
+ nxagentInitPointerMap();
+ }
+
+ break;
+ }
+ default:
+ {
+ /*
+ * Let's check if this is a XKB
+ * state modification event.
+ */
+
+ if (nxagentHandleKeyboardEvent(&X) == 0 && nxagentHandleXFixesSelectionNotify(&X) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! Unhandled event code [%d].\n",
+ X.type);
+ #endif
+ }
+
+ break;
+ }
+
+ } /* End of switch (X.type) */
+
+ if (X.xany.serial < lastEventSerial)
+ {
+ /*
+ * Start over.
+ */
+
+ nxagentDeleteStaticResizedWindow(0);
+ }
+ else
+ {
+ nxagentDeleteStaticResizedWindow(X.xany.serial - 1);
+ }
+
+ lastEventSerial = X.xany.serial;
+
+ } /* End of while (...) */
+
+ /*
+ * Send the exposed regions to the clients.
+ */
+
+ nxagentForwardRemoteExpose();
+
+ /*
+ * Handle the agent window's changes.
+ */
+
+ if (closeSession)
+ {
+ if (nxagentOption(Persistent))
+ {
+ if (nxagentNoDialogIsRunning)
+ {
+ nxagentLaunchDialog(DIALOG_SUSPEND_SESSION);
+ }
+ }
+ else
+ {
+ if (nxagentNoDialogIsRunning)
+ {
+ nxagentLaunchDialog(DIALOG_KILL_SESSION);
+ }
+ }
+ }
+
+ if (minimize)
+ {
+ nxagentWMDetect();
+
+ if (nxagentWMIsRunning)
+ {
+ if (nxagentOption(AllScreens))
+ {
+ nxagentMinimizeFromFullScreen(pScreen);
+ }
+ else
+ {
+ XIconifyWindow(nxagentDisplay, nxagentDefaultWindows[0],
+ DefaultScreen(nxagentDisplay));
+ }
+ }
+ }
+
+ if (switchFullscreen)
+ {
+ if (nxagentOption(AllScreens) == 1 && nxagentOption(Fullscreen) == 1)
+ {
+ nxagentSwitchAllScreens(pScreen, 0);
+ }
+ else
+ {
+ nxagentSwitchFullscreen(pScreen, !nxagentOption(Fullscreen));
+ }
+ }
+
+ if (switchAllScreens)
+ {
+ if (nxagentOption(AllScreens) == 0 && nxagentOption(Fullscreen) == 1)
+ {
+ nxagentSwitchFullscreen(pScreen, 0);
+ }
+ else
+ {
+ nxagentSwitchAllScreens(pScreen, !nxagentOption(AllScreens));
+ }
+ }
+
+ if (startKbd)
+ {
+ if (xkbdRunning)
+ {
+ #ifdef NXAGENT_XKBD_DEBUG
+ fprintf(stderr, "Events: nxkbd now is NOT running: %d, %d\n",
+ X.xkey.keycode, escapecode);
+ #endif
+
+ xkbdRunning = False;
+
+ kill(pidkbd, 9);
+ }
+ else
+ {
+ char kbddisplay[6];
+ char *kbdargs[6];
+
+ strcpy(kbddisplay,":");
+ strncat(kbddisplay, display, 4);
+
+ kbdargs[0] = "nxkbd";
+ kbdargs[1] = "-geometry";
+ kbdargs[2] = "240x70+0+250";
+ kbdargs[3] = "-display";
+ kbdargs[4] = kbddisplay;
+ kbdargs[5] = NULL;
+
+ switch (pidkbd = fork())
+ {
+ case 0:
+ {
+ execvp(kbdargs[0], kbdargs);
+
+ #ifdef NXAGENT_XKBD_DEBUG
+ fprintf(stderr, "Events: The execvp of nxkbd process failed.\n");
+ #endif
+
+ exit(1);
+
+ break;
+ }
+ case -1:
+ {
+ #ifdef NXAGENT_XKBD_DEBUG
+ fprintf(stderr, "Events: Can't fork to run the nxkbd process.\n");
+ #endif
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ #ifdef NXAGENT_XKBD_DEBUG
+ fprintf(stderr, "Events: The nxkbd process now running with [%d][%d].\n",
+ X.xkey.keycode, escapecode);
+ #endif
+
+ xkbdRunning = True;
+ }
+ }
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End read]\n");
+ #endif
+
+ /*
+ * Let the underlying X server code
+ * process the input events.
+ */
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin events]\n");
+ #endif
+
+ ProcessInputEvents();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Output pending flag is [%d] critical [%d].\n",
+ NewOutputPending, CriticalOutputPending);
+ #endif
+
+ /*
+ * Write the events to our clients. We may
+ * flush only in the case of critical output
+ * but this doesn't seem beneficial.
+ *
+ * if (CriticalOutputPending == 1)
+ * {
+ * FlushAllOutput();
+ * }
+ */
+
+ if (NewOutputPending == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchEvents: Flushed the processed events to clients.\n");
+ #endif
+
+ FlushAllOutput();
+ }
+
+ #ifdef TEST
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ fprintf(stderr, "nxagentDispatchEvents: WARNING! More events need to be dispatched.\n");
+ }
+
+ #endif
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End events]\n");
+ #endif
+}
+
+/*
+ * Functions providing the ad-hoc handling
+ * of the remote X events.
+ */
+
+int nxagentHandleKeyPress(XEvent *X, enum HandleEventResult *result)
+{
+ xEvent x;
+
+ if (nxagentXkbState.Initialized == 0)
+ {
+ if (X -> xkey.keycode == nxagentCapsLockKeycode)
+ {
+ nxagentXkbCapsTrap = 1;
+ }
+ else if (X -> xkey.keycode == nxagentNumLockKeycode)
+ {
+ nxagentXkbNumTrap = 1;
+ }
+
+ nxagentInitKeyboardState();
+
+ nxagentXkbCapsTrap = 0;
+ nxagentXkbNumTrap = 0;
+ }
+
+ if (nxagentCheckSpecialKeystroke(&X -> xkey, result))
+ {
+ return 1;
+ }
+
+ if (X -> xkey.keycode == nxagentCapsLockKeycode)
+ {
+ nxagentXkbState.Caps = (~nxagentXkbState.Caps & 1);
+ }
+ else if (X -> xkey.keycode == nxagentNumLockKeycode)
+ {
+ nxagentXkbState.Num = (~nxagentXkbState.Num & 1);
+ }
+
+ nxagentLastEventTime = nxagentLastKeyPressTime = GetTimeInMillis();
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = KeyPress;
+ x.u.u.detail = nxagentConvertKeycode(X -> xkey.keycode);
+ x.u.keyButtonPointer.time = nxagentLastKeyPressTime;
+
+ nxagentLastServerTime = X -> xkey.time;
+
+ mieqEnqueue(&x);
+
+ CriticalOutputPending = 1;
+
+ return 1;
+}
+
+int nxagentHandlePropertyNotify(XEvent *X)
+{
+ int resource;
+
+ if (nxagentOption(Rootless) && !nxagentNotifyMatchChangeProperty((XPropertyEvent *) X))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandlePropertyNotify: Property %ld on window %lx.\n",
+ X -> xproperty.atom, X -> xproperty.window);
+ #endif
+
+ if (nxagentWindowPtr(X -> xproperty.window) != NULL)
+ {
+ resource = NXGetCollectPropertyResource(nxagentDisplay);
+
+ if (resource == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandlePropertyNotify: WARNING! Asynchronous get property queue is full.\n");
+ #endif
+
+ return 0;
+ }
+
+ NXCollectProperty(nxagentDisplay, resource,
+ X -> xproperty.window, X -> xproperty.atom, 0,
+ MAX_RETRIEVED_PROPERTY_SIZE, False, AnyPropertyType);
+
+ nxagentPropertyRequests[resource].window = X -> xproperty.window;
+ nxagentPropertyRequests[resource].property = X -> xproperty.atom;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentHandlePropertyNotify: Failed to look up remote window property.\n");
+ }
+ #endif
+ }
+
+ return 1;
+}
+
+int nxagentHandleExposeEvent(XEvent *X)
+{
+ WindowPtr pWin = NULL;
+ Window window = None;
+
+ RegionRec sum;
+ RegionRec add;
+ BoxRec box;
+ int index = 0;
+ int overlap = 0;
+
+ StaticResizedWindowStruct *resizedWinPtr = NULL;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleExposeEvent: Checking remote expose events.\n");
+
+ fprintf(stderr, "nxagentHandleExposeEvent: Looking for window id [%ld].\n",
+ X -> xexpose.window);
+ #endif
+
+ window = X -> xexpose.window;
+
+ pWin = nxagentWindowPtr(window);
+
+ if (pWin != NULL)
+ {
+ RegionInit(&sum, (BoxRec *) NULL, 1);
+/*
+FIXME: This can be maybe optimized by consuming the
+ events that do not match the predicate.
+*/
+ do
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleExposeEvent: Adding event for window id [%ld].\n",
+ X -> xexpose.window);
+ #endif
+
+ box.x1 = pWin -> drawable.x + wBorderWidth(pWin) + X -> xexpose.x;
+ box.y1 = pWin -> drawable.y + wBorderWidth(pWin) + X -> xexpose.y;
+
+ resizedWinPtr = nxagentFindStaticResizedWindow(X -> xany.serial);
+
+ while (resizedWinPtr)
+ {
+ if (resizedWinPtr -> pWin == pWin)
+ {
+ box.x1 += resizedWinPtr -> offX;
+ box.y1 += resizedWinPtr -> offY;
+ }
+
+ resizedWinPtr = resizedWinPtr -> prev;
+ }
+
+ box.x2 = box.x1 + X -> xexpose.width;
+ box.y2 = box.y1 + X -> xexpose.height;
+
+ RegionInit(&add, &box, 1);
+
+ RegionAppend(&sum, &add);
+
+ RegionUninit(&add);
+
+ if (X -> xexpose.count == 0)
+ {
+ break;
+ }
+ }
+ while (nxagentCheckEvents(nxagentDisplay, X, nxagentExposurePredicate,
+ (XPointer) &window) == 1);
+
+ RegionValidate(&sum, &overlap);
+
+ RegionIntersect(&sum, &sum,
+ &pWin->drawable.pScreen->root->winSize);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleExposeEvent: Sending events for window id [%ld].\n",
+ X -> xexpose.window);
+ #endif
+
+ /*
+ * If the agent has already sent auto-generated expose,
+ * save received exposes for later processing.
+ */
+
+ index = nxagentLookupByWindow(pWin);
+
+ if (index == -1)
+ {
+ miWindowExposures(pWin, &sum, NullRegion);
+ }
+ else
+ {
+ RegionTranslate(&sum, -pWin -> drawable.x, -pWin -> drawable.y);
+
+ if (nxagentExposeQueue.exposures[index].remoteRegion == NullRegion)
+ {
+ nxagentExposeQueue.exposures[index].remoteRegion = RegionCreate(NULL, 1);
+ }
+
+ RegionUnion(nxagentExposeQueue.exposures[index].remoteRegion,
+ nxagentExposeQueue.exposures[index].remoteRegion, &sum);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleExposeEvent: Added region for window [%ld] to position [%d].\n",
+ nxagentWindow(pWin), index);
+ #endif
+
+ if (X -> xexpose.count == 0)
+ {
+ nxagentExposeQueue.exposures[index].remoteRegionIsCompleted = True;
+ }
+ else
+ {
+ nxagentExposeQueue.exposures[index].remoteRegionIsCompleted = False;
+ }
+ }
+
+ if (nxagentRootTileWindow != NULL)
+ {
+ if (nxagentWindowPriv(nxagentRootTileWindow) -> window == nxagentWindowPriv(pWin) -> window &&
+ nxagentSplashCount == 1 && X -> xexpose.count == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleExposeEvent: Clearing root tile window id [%ld].\n",
+ nxagentWindowPriv(nxagentRootTileWindow) -> window);
+ #endif
+
+ XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow) -> window);
+ }
+ }
+
+ RegionUninit(&sum);
+ }
+
+ return 1;
+}
+
+int nxagentHandleGraphicsExposeEvent(XEvent *X)
+{
+ /*
+ * Send an expose event to client, instead of graphics
+ * expose. If target drawable is a backing pixmap, send
+ * expose event for the saved window, else do nothing.
+ */
+
+ RegionPtr exposeRegion;
+ BoxRec rect;
+ WindowPtr pWin;
+ StoringPixmapPtr pStoringPixmapRec = NULL;
+ miBSWindowPtr pBSwindow = NULL;
+ int drawableType;
+
+ pWin = nxagentWindowPtr(X -> xgraphicsexpose.drawable);
+
+ if (pWin != NULL)
+ {
+ drawableType = DRAWABLE_WINDOW;
+ }
+ else
+ {
+ drawableType = DRAWABLE_PIXMAP;
+ }
+
+ if (drawableType == DRAWABLE_PIXMAP)
+ {
+ pStoringPixmapRec = nxagentFindItemBSPixmapList(X -> xgraphicsexpose.drawable);
+
+ if (pStoringPixmapRec == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleGraphicsExposeEvent: WARNING! Storing pixmap not found.\n");
+ #endif
+
+ return 1;
+ }
+
+ pBSwindow = (miBSWindowPtr) pStoringPixmapRec -> pSavedWindow -> backStorage;
+
+ if (pBSwindow == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleGraphicsExposeEvent: WARNING! Back storage not found.\n");
+ #endif
+
+ return 1;
+ }
+
+ pWin = pStoringPixmapRec -> pSavedWindow;
+ }
+
+ /*
+ * Rectangle affected by GraphicsExpose
+ * event.
+ */
+
+ rect.x1 = X -> xgraphicsexpose.x;
+ rect.y1 = X -> xgraphicsexpose.y;
+ rect.x2 = rect.x1 + X -> xgraphicsexpose.width;
+ rect.y2 = rect.y1 + X -> xgraphicsexpose.height;
+
+ exposeRegion = RegionCreate(&rect, 0);
+
+ if (drawableType == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleGraphicsExposeEvent: Handling GraphicsExpose event on pixmap with id"
+ " [%lu].\n", X -> xgraphicsexpose.drawable);
+ #endif
+
+ /*
+ * The exposeRegion coordinates are relative
+ * to the pixmap to which GraphicsExpose
+ * event refers. But the BS coordinates of
+ * the savedRegion are relative to the
+ * window.
+ */
+
+ RegionTranslate(exposeRegion, pStoringPixmapRec -> backingStoreX,
+ pStoringPixmapRec -> backingStoreY);
+
+ /*
+ * We remove from SavedRegion the part
+ * affected by the GraphicsExpose event.
+ */
+
+ RegionSubtract(&(pBSwindow -> SavedRegion), &(pBSwindow -> SavedRegion),
+ exposeRegion);
+ }
+
+ /*
+ * Store the exposeRegion in order to send
+ * the expose event later. The coordinates
+ * must be relative to the screen.
+ */
+
+ RegionTranslate(exposeRegion, pWin -> drawable.x, pWin -> drawable.y);
+
+ RegionUnion(nxagentRemoteExposeRegion, nxagentRemoteExposeRegion, exposeRegion);
+
+ RegionDestroy(exposeRegion);
+
+ return 1;
+}
+
+int nxagentHandleClientMessageEvent(XEvent *X, enum HandleEventResult *result)
+{
+ WindowPtr pWin;
+
+ *result = doNothing;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleClientMessageEvent: ClientMessage event window [%ld] with "
+ "type [%ld] format [%d].\n", X -> xclient.window, X -> xclient.message_type,
+ X -> xclient.format);
+ #endif
+
+ /*
+ * If window is 0, message_type is 0 and format is
+ * 32 then we assume event is coming from proxy.
+ */
+
+ if (X -> xclient.window == 0 &&
+ X -> xclient.message_type == 0 &&
+ X -> xclient.format == 32)
+ {
+ nxagentHandleProxyEvent(X);
+
+ return 1;
+ }
+
+ if (nxagentOption(Rootless))
+ {
+ Atom message_type = nxagentRemoteToLocalAtom(X -> xclient.message_type);
+
+ if (!ValidAtom(message_type))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleClientMessageEvent: WARNING Invalid type in client message.\n");
+ #endif
+
+ return 0;
+ }
+
+ pWin = nxagentWindowPtr(X -> xclient.window);
+
+ if (pWin == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "WARNING: Invalid window in ClientMessage.\n");
+ #endif
+
+ return 0;
+ }
+
+ if (message_type == MakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), False))
+ {
+ #ifdef TEST
+ char *message_data;
+ #endif
+
+ xEvent x;
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = ClientMessage;
+ x.u.u.detail = X -> xclient.format;
+
+ x.u.clientMessage.window = pWin -> drawable.id;
+ x.u.clientMessage.u.l.type = message_type;
+ x.u.clientMessage.u.l.longs0 = nxagentRemoteToLocalAtom(X -> xclient.data.l[0]);
+ x.u.clientMessage.u.l.longs1 = GetTimeInMillis();
+
+ if (!ValidAtom(x.u.clientMessage.u.l.longs0))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleClientMessageEvent: WARNING Invalid value in client message "
+ "of type WM_PROTOCOLS.\n");
+ #endif
+
+ return 0;
+ }
+ #ifdef TEST
+ else
+ {
+ message_data = validateString(NameForAtom(x.u.clientMessage.u.l.longs0));
+ }
+
+ fprintf(stderr, "nxagentHandleClientMessageEvent: Sent client message of type WM_PROTOCOLS "
+ "and value [%s].\n", message_data);
+ #endif
+
+ TryClientEvents(wClient(pWin), &x, 1, 1, 1, 0);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleClientMessageEvent: Ignored message type %ld [%s].\n",
+ (long int) message_type, validateString(NameForAtom(message_type)));
+ #endif
+
+ return 0;
+ }
+
+ return 1;
+ }
+
+ if (X -> xclient.message_type == nxagentAtoms[1]) /* WM_PROTOCOLS */
+ {
+ Atom deleteWMatom, wmAtom;
+
+ wmAtom = (Atom) X -> xclient.data.l[0];
+
+ deleteWMatom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */
+
+ if (wmAtom == deleteWMatom)
+ {
+ if (nxagentOnce && (nxagentClients == 0))
+ {
+ GiveUp(0);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "Events: WM_DELETE_WINDOW arrived Atom = %ld.\n", wmAtom);
+ #endif
+
+ if (X -> xclient.window == nxagentIconWindow)
+ {
+ XMapRaised(nxagentDisplay, nxagentFullscreenWindow);
+
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+
+ }
+
+ if (X -> xclient.window == (nxagentOption(Fullscreen) ?
+ nxagentIconWindow : nxagentDefaultWindows[0]) ||
+ nxagentWMIsRunning == 0)
+ {
+ *result = doCloseSession;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+int nxagentHandleKeyboardEvent(XEvent *X)
+{
+ XkbEvent *xkbev = (XkbEvent *) X;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Handling event with caps [%d] num [%d] locked [%d].\n",
+ nxagentXkbState.Caps, nxagentXkbState.Num, nxagentXkbState.Locked);
+ #endif
+
+ if (xkbev -> type == nxagentXkbInfo.EventBase + XkbEventCode &&
+ xkbev -> any.xkb_type == XkbStateNotify)
+ {
+ nxagentXkbState.Locked = xkbev -> state.locked_mods;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Updated XKB locked modifier bits to [%x].\n",
+ nxagentXkbState.Locked);
+ #endif
+
+ nxagentXkbState.Initialized = 1;
+
+ if (nxagentXkbState.Caps == 0 &&
+ (nxagentXkbState.Locked & CAPSFLAG_IN_EVENT))
+ {
+ nxagentXkbState.Caps = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [66] to engage capslock.\n");
+ #endif
+
+ if (!nxagentXkbCapsTrap)
+ {
+ nxagentSendFakeKey(66);
+ }
+ }
+
+ if (nxagentXkbState.Caps == 1 &&
+ !(nxagentXkbState.Locked & CAPSFLAG_IN_EVENT))
+ {
+ nxagentXkbState.Caps = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [66] to release capslock.\n");
+ #endif
+
+ nxagentSendFakeKey(66);
+ }
+
+ if (nxagentXkbState.Caps == 0 &&
+ !(nxagentXkbState.Locked & CAPSFLAG_IN_EVENT) &&
+ nxagentXkbCapsTrap)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [66] to release capslock.\n");
+ #endif
+
+ nxagentSendFakeKey(66);
+ }
+
+ if (nxagentXkbState.Num == 0 &&
+ (nxagentXkbState.Locked & NUMFLAG_IN_EVENT))
+ {
+ nxagentXkbState.Num = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to engage numlock.\n");
+ #endif
+
+ if (!nxagentXkbNumTrap)
+ {
+ nxagentSendFakeKey(77);
+ }
+ }
+
+ if (nxagentXkbState.Num == 1 &&
+ !(nxagentXkbState.Locked & NUMFLAG_IN_EVENT))
+ {
+ nxagentXkbState.Num = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to release numlock.\n");
+ #endif
+
+ nxagentSendFakeKey(77);
+ }
+
+ if (nxagentXkbState.Num == 0 &&
+ !(nxagentXkbState.Locked & NUMFLAG_IN_EVENT) &&
+ nxagentXkbNumTrap)
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleKeyboardEvent: Sending fake key [77] to release numlock.\n");
+ #endif
+
+ nxagentSendFakeKey(77);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+int nxagentHandleXFixesSelectionNotify(XEvent *X)
+{
+ int i;
+ Atom local;
+
+ XFixesSelectionEvent *xfixesEvent = (XFixesSelectionEvent *) X;
+
+ if (nxagentXFixesInfo.Initialized == 0 ||
+ xfixesEvent -> type != (nxagentXFixesInfo.EventBase + XFixesSelectionNotify))
+ return 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Handling event.\n");
+ #endif
+
+ local = nxagentRemoteToLocalAtom(xfixesEvent -> xfixesselection.selection);
+
+ if (SelectionCallback)
+ {
+ i = 0;
+
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != local)
+ i++;
+
+ if (i < NumCurrentSelections)
+ {
+ SelectionInfoRec info;
+
+ if (CurrentSelections[i].client != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Do nothing.\n");
+ #endif
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Calling callbacks for %d [%s] selection.\n",
+ CurrentSelections[i].selection, NameForAtom(CurrentSelections[i].selection));
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleXFixesSelectionNotify: Subtype ");
+
+ switch (xfixesEvent -> xfixesselection.subtype)
+ {
+ case SelectionSetOwner:
+ fprintf(stderr, "SelectionSetOwner.\n");
+ break;
+ case SelectionWindowDestroy:
+ fprintf(stderr, "SelectionWindowDestroy.\n");
+ break;
+ case SelectionClientClose:
+ fprintf(stderr, "SelectionClientClose.\n");
+ break;
+ default:
+ fprintf(stderr, ".\n");
+ break;
+ }
+ #endif
+
+ info.selection = &CurrentSelections[i];
+ info.kind = xfixesEvent->xfixesselection.subtype;
+ CallCallbacks(&SelectionCallback, &info);
+ }
+ }
+ return 1;
+}
+
+int nxagentHandleProxyEvent(XEvent *X)
+{
+ switch (X -> xclient.data.l[0])
+ {
+ case NXNoSplitNotify:
+ case NXStartSplitNotify:
+ {
+ /*
+ * We should never receive such events
+ * in the event loop, as they should
+ * be caught at the time the split is
+ * initiated.
+ */
+
+ #ifdef PANIC
+
+ int client = (int) X -> xclient.data.l[1];
+
+ if (X -> xclient.data.l[0] == NXNoSplitNotify)
+ {
+ fprintf(stderr, "nxagentHandleProxyEvent: PANIC! NXNoSplitNotify received "
+ "with client [%d].\n", client);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentHandleProxyEvent: PANIC! NXStartSplitNotify received "
+ "with client [%d].\n", client);
+ }
+
+ #endif
+
+ return 1;
+ }
+ case NXCommitSplitNotify:
+ {
+ /*
+ * We need to commit an image. Image can be the
+ * result of a PutSubImage() generated by Xlib,
+ * so there can be more than a single image to
+ * commit, even if only one PutImage was perfor-
+ * med by the agent.
+ */
+
+ int client = (int) X -> xclient.data.l[1];
+ int request = (int) X -> xclient.data.l[2];
+ int position = (int) X -> xclient.data.l[3];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleProxyEvent: NXCommitSplitNotify received with "
+ "client [%d] request [%d] and position [%d].\n",
+ client, request, position);
+ #endif
+
+ nxagentHandleCommitSplitEvent(client, request, position);
+
+ return 1;
+ }
+ case NXEndSplitNotify:
+ {
+ /*
+ * All images for the split were transferred and
+ * we need to restart the client.
+ */
+
+ int client = (int) X -> xclient.data.l[1];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleProxyEvent: NXEndSplitNotify received with "
+ "client [%d].\n", client);
+ #endif
+
+ nxagentHandleEndSplitEvent(client);
+
+ return 1;
+ }
+ case NXEmptySplitNotify:
+ {
+ /*
+ * All splits have been completed and none remain.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleProxyEvent: NXEmptySplitNotify received.\n");
+ #endif
+
+ nxagentHandleEmptySplitEvent();
+
+ return 1;
+ }
+ case NXCollectPropertyNotify:
+ {
+ #ifdef TEST
+ int resource = (int) X -> xclient.data.l[1];
+
+ fprintf(stderr, "nxagentHandleProxyEvent: NXCollectPropertyNotify received with resource [%d].\n",
+ resource);
+ #endif
+
+ nxagentHandleCollectPropertyEvent(X);
+
+ return 1;
+ }
+ case NXCollectGrabPointerNotify:
+ {
+ int resource = (int) X -> xclient.data.l[1];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleProxyEvent: NXCollectGrabPointerNotify received with resource [%d].\n",
+ resource);
+ #endif
+
+ nxagentHandleCollectGrabPointerEvent(resource);
+
+ return 1;
+ }
+ case NXCollectInputFocusNotify:
+ {
+ int resource = (int) X -> xclient.data.l[1];
+
+ /*
+ * This is not used at the present moment.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleProxyEvent: NXCollectInputFocusNotify received with resource [%d].\n",
+ resource);
+ #endif
+
+ nxagentHandleCollectInputFocusEvent(resource);
+
+ return 1;
+ }
+ default:
+ {
+ /*
+ * Not a recognized ClientMessage event.
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleProxyEvent: WARNING! Not a recognized ClientMessage proxy event [%d].\n",
+ (int) X -> xclient.data.l[0]);
+ #endif
+
+ return 0;
+ }
+ }
+}
+
+/*
+ * In this function it is assumed that we never
+ * get a configure with both stacking order and
+ * geometry changed, this way we can ignore
+ * stacking changes if the geometry has changed.
+ */
+
+int nxagentCheckWindowConfiguration(XConfigureEvent* X)
+{
+ static int x = 0;
+ static int y = 0;
+ static int width = 0;
+ static int height = 0;
+ static Window win = None;
+ Bool geometryChanged = False;
+
+ XlibWindow root_return = 0;
+ XlibWindow parent_return = 0;
+ XlibWindow *children_return = NULL;
+ unsigned int nchildren_return = 0;
+ Status result;
+
+ if (win == X -> window)
+ {
+ if (x != X -> x ||
+ y != X -> y ||
+ width != X -> width ||
+ height != X -> height)
+ {
+ geometryChanged = True;
+ }
+ }
+
+ win = X -> window;
+
+ x = X -> x;
+ y = X -> y;
+ width = X -> width;
+ height = X -> height;
+
+ if (geometryChanged)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckWindowConfiguration: Configure frame. No restack.\n");
+ #endif
+
+ return 1;
+ }
+
+ #ifdef TEST
+ {
+ WindowPtr pSib;
+
+ fprintf(stderr, "nxagentCheckWindowConfiguration: Before restacking top level window [%p]\n",
+ (void *) nxagentWindowPtr(X -> window));
+
+ for (pSib = screenInfo.screens[0]->root -> firstChild; pSib; pSib = pSib -> nextSib)
+ {
+ fprintf(stderr, "nxagentCheckWindowConfiguration: Top level window: [%p].\n",
+ (void *) pSib);
+ }
+ }
+ #endif
+
+ result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ &root_return, &parent_return, &children_return, &nchildren_return);
+
+ if (result)
+ {
+ nxagentRootlessRestack(children_return, nchildren_return);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckWindowConfiguration: WARNING! Failed QueryTree request.\n");
+ #endif
+ }
+
+ if (result && nchildren_return)
+ {
+ XFree(children_return);
+ }
+
+ #if 0
+ fprintf(stderr, "nxagentCheckWindowConfiguration: Trees match: %s\n",
+ nxagentRootlessTreesMatch() ? "Yes" : "No");
+ #endif
+
+ return 1;
+}
+
+int nxagentHandleConfigureNotify(XEvent* X)
+{
+ if (nxagentOption(Rootless) == True)
+ {
+ ClientPtr pClient;
+ WindowPtr pWinWindow;
+ WindowPtr pWin;
+ int sendEventAnyway = 0;
+
+ pWinWindow = nxagentWindowPtr(X -> xconfigure.window);
+
+ #ifdef TEST
+ {
+ WindowPtr pWinEvent = nxagentWindowPtr(X -> xconfigure.event);
+
+ fprintf(stderr, "nxagentHandleConfigureNotify: Generating window is [%p][%ld] target [%p][%ld].\n",
+ (void *) pWinEvent, X -> xconfigure.event, (void *) pWinWindow, X -> xconfigure.window);
+ }
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConfigureNotify: New configuration for window [%p][%ld] is [%d][%d][%d][%d] "
+ "send_event [%i].\n", (void *) pWinWindow, X -> xconfigure.window,
+ X -> xconfigure.x, X -> xconfigure.y, X -> xconfigure.width,
+ X -> xconfigure.height, X -> xconfigure.send_event);
+ #endif
+
+ if ((pWin = nxagentRootlessTopLevelWindow(X -> xconfigure.window)) != NULL)
+ {
+ /*
+ * Cheking for new geometry or stacking order changes.
+ */
+
+ nxagentCheckWindowConfiguration((XConfigureEvent*)X);
+
+ return 1;
+ }
+
+ if (nxagentWindowTopLevel(pWinWindow) && !X -> xconfigure.override_redirect)
+ {
+ XID values[5];
+ Mask mask = 0;
+
+ register XID *value = values;
+
+ pClient = wClient(pWinWindow);
+
+ if (X -> xconfigure.send_event || !nxagentWMIsRunning ||
+ X -> xconfigure.override_redirect)
+ {
+ *value++ = (XID)X -> xconfigure.x;
+ *value++ = (XID)X -> xconfigure.y;
+
+ /*
+ * nxagentWindowPriv(pWinWindow)->x = X -> xconfigure.x;
+ * nxagentWindowPriv(pWinWindow)->y = X -> xconfigure.y;
+ */
+
+ mask |= CWX | CWY;
+ }
+
+ *value++ = (XID)X -> xconfigure.width;
+ *value++ = (XID)X -> xconfigure.height;
+ *value++ = (XID)X -> xconfigure.border_width;
+
+ /*
+ * We don't need width and height here.
+ *
+ * nxagentWindowPriv(pWinWindow)->width = X -> xconfigure.width;
+ * nxagentWindowPriv(pWinWindow)->height = X -> xconfigure.height;
+ */
+
+ mask |= CWHeight | CWWidth | CWBorderWidth;
+
+ nxagentScreenTrap = 1;
+
+ ConfigureWindow(pWinWindow, mask, (XID *) values, pClient);
+
+ nxagentScreenTrap = 0;
+
+ nxagentCheckWindowConfiguration((XConfigureEvent*)X);
+
+ /*
+ * This workaround should help with
+ * Java 1.6.0 that seems to ignore
+ * non-synthetic events.
+ */
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConfigureNotify: Apply workaround for NXWin.\n");
+ #endif
+
+ sendEventAnyway = 1;
+ }
+
+ if (sendEventAnyway || X -> xconfigure.send_event)
+ {
+ xEvent x;
+
+ memset(&x, 0, sizeof(xEvent));
+ x.u.u.type = X -> xconfigure.type;
+ x.u.u.type |= 0x80;
+
+ x.u.configureNotify.event = pWinWindow -> drawable.id;
+ x.u.configureNotify.window = pWinWindow -> drawable.id;
+
+ if (pWinWindow -> nextSib)
+ {
+ x.u.configureNotify.aboveSibling = pWinWindow -> nextSib -> drawable.id;
+ }
+ else
+ {
+ x.u.configureNotify.aboveSibling = None;
+ }
+
+ x.u.configureNotify.x = X -> xconfigure.x;
+ x.u.configureNotify.y = X -> xconfigure.y;
+ x.u.configureNotify.width = X -> xconfigure.width;
+ x.u.configureNotify.height = X -> xconfigure.height;
+ x.u.configureNotify.borderWidth = X -> xconfigure.border_width;
+ x.u.configureNotify.override = X -> xconfigure.override_redirect;
+
+ TryClientEvents(pClient, &x, 1, 1, 1, 0);
+ }
+
+ return 1;
+ }
+ }
+ else
+ {
+ /*
+ * Save the position of the agent default window. Don't
+ * save the values if the agent is in fullscreen mode.
+ *
+ * If we use these values to restore the position of a
+ * window after that we have dynamically changed the
+ * fullscreen attribute, depending on the behaviour of
+ * window manager, we could be not able to place the
+ * window exactly in the requested position, so let the
+ * window manager do the job for us.
+ */
+
+ ScreenPtr pScreen = nxagentScreen(X -> xconfigure.window);
+
+ Bool doRandR = False;
+ struct timeval timeout;
+
+ if (X -> xconfigure.window == nxagentDefaultWindows[pScreen -> myNum])
+ {
+ if (nxagentOption(AllScreens) == 0)
+ {
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ if (nxagentOption(Width) != X -> xconfigure.width ||
+ nxagentOption(Height) != X -> xconfigure.height ||
+ nxagentOption(X) != X -> xconfigure.x ||
+ nxagentOption(Y) != X -> xconfigure.y)
+ {
+ Bool newEvents = False;
+
+ doRandR = True;
+
+ NXFlushDisplay(nxagentDisplay, NXFlushLink);
+
+ do
+ {
+ newEvents = False;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 500 * 1000;
+
+ nxagentWaitEvents(nxagentDisplay, &timeout);
+
+ /*
+ * This should also flush
+ * the NX link for us.
+ */
+
+ XSync(nxagentDisplay, 0);
+
+ while (XCheckTypedWindowEvent(nxagentDisplay, nxagentDefaultWindows[pScreen -> myNum],
+ ConfigureNotify, X))
+ {
+ newEvents = True;
+ }
+
+ } while (newEvents);
+ }
+ }
+
+ if (nxagentWMIsRunning == 0 || X -> xconfigure.send_event)
+ {
+ nxagentChangeOption(X, X -> xconfigure.x);
+ nxagentChangeOption(Y, X -> xconfigure.y);
+ }
+
+ if (nxagentOption(Shadow) == 1 && nxagentOption(DesktopResize) == 1 &&
+ (nxagentOption(Width) != X -> xconfigure.width ||
+ nxagentOption(Height) != X -> xconfigure.height))
+ {
+ nxagentShadowResize = 1;
+ }
+
+ nxagentChangeOption(Width, X -> xconfigure.width);
+ nxagentChangeOption(Height, X -> xconfigure.height);
+
+ nxagentChangeOption(ViewportXSpan, (int) X -> xconfigure.width -
+ (int) nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, (int) X -> xconfigure.height -
+ (int) nxagentOption(RootHeight));
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ /* if in shadowing mode or if neither size nor position have
+ changed we do not need to adjust RandR */
+ /* FIXME: Comment makes no sense */
+ if (nxagentOption(Shadow) == 1 ||
+ (nxagentOption(Width) == nxagentOption(RootWidth) &&
+ nxagentOption(Height) == nxagentOption(RootHeight) &&
+ nxagentOption(X) == nxagentOption(RootX) &&
+ nxagentOption(Y) == nxagentOption(RootY)))
+ {
+ doRandR = False;
+ }
+
+ nxagentChangeOption(Width, X -> xconfigure.width);
+ nxagentChangeOption(Height, X -> xconfigure.height);
+
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
+ X -> xconfigure.width, X -> xconfigure.height);
+
+ if (nxagentOption(Fullscreen) == 0)
+ {
+ nxagentMoveViewport(pScreen, 0, 0);
+ }
+ else
+ {
+ nxagentChangeOption(RootX, (nxagentOption(Width) -
+ nxagentOption(RootWidth)) / 2);
+ nxagentChangeOption(RootY, (nxagentOption(Height) -
+ nxagentOption(RootHeight)) / 2);
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) -
+ nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) -
+ nxagentOption(RootHeight));
+
+ nxagentUpdateViewportFrame(0, 0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight));
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root),
+ nxagentOption(RootX), nxagentOption(RootY));
+ }
+
+ if (doRandR)
+ {
+ #ifdef TEST
+ fprintf(stderr,"nxagentHandleConfigureNotify: Width %d Height %d.\n",
+ nxagentOption(Width), nxagentOption(Height));
+ #endif
+
+ nxagentChangeScreenConfig(0, nxagentOption(Width),
+ nxagentOption(Height), 0, 0);
+ }
+ }
+
+ return 1;
+ }
+ else
+ {
+ if ( (X -> xconfigure.window == DefaultRootWindow(nxagentDisplay)) || nxagentFullscreenWindow )
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConfigureNotify: remote root window has changed: %d,%d %dx%d\n", X -> xconfigure.x, X -> xconfigure.y, X -> xconfigure.width, X -> xconfigure.height);
+ #endif
+
+ nxagentChangeOption(RootX, X -> xconfigure.x);
+ nxagentChangeOption(RootY, X -> xconfigure.y);
+ nxagentChangeOption(RootWidth, X -> xconfigure.width);
+ nxagentChangeOption(RootHeight, X -> xconfigure.height);
+
+ nxagentChangeScreenConfig(0, nxagentOption(Width),
+ nxagentOption(Height), 0, 0);
+
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int nxagentHandleReparentNotify(XEvent* X)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleReparentNotify: Going to handle a new reparent event.\n");
+ #endif
+
+ if (nxagentOption(Rootless))
+ {
+ WindowPtr pWin;
+
+ XlibWindow w;
+ XlibWindow root_return = 0;
+ XlibWindow parent_return = 0;
+ XlibWindow *children_return = NULL;
+ unsigned int nchildren_return = 0;
+ Status result;
+
+ pWin = nxagentWindowPtr(X -> xreparent.window);
+
+ #ifdef TEST
+
+ {
+ WindowPtr pParent = nxagentWindowPtr(X -> xreparent.parent);
+ WindowPtr pEvent = nxagentWindowPtr(X -> xreparent.event);
+
+ fprintf(stderr, "nxagentHandleReparentNotify: event %p[%lx] window %p[%lx] parent %p[%lx] at (%d, %d)\n",
+ (void*)pEvent, X -> xreparent.event, (void*)pWin, X -> xreparent.window,
+ (void*)pParent, X -> xreparent.parent, X -> xreparent.x, X -> xreparent.y);
+ }
+
+ #endif
+
+ if (nxagentWindowTopLevel(pWin))
+ {
+ /*
+ * If the window manager reparents our top level
+ * window, we need to know the new top level
+ * ancestor.
+ */
+
+ w = None;
+ parent_return = X -> xreparent.parent;
+
+ while (parent_return != RootWindow(nxagentDisplay, 0))
+ {
+ w = parent_return;
+ result = XQueryTree(nxagentDisplay, w, &root_return,
+ &parent_return, &children_return, &nchildren_return);
+
+ if (!result)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! Failed QueryTree request.\n");
+ #endif
+
+ break;
+ }
+
+ if (result && children_return)
+ {
+ XFree(children_return);
+ }
+ }
+
+ if (w && !nxagentWindowPtr(w))
+ {
+ XSelectInput(nxagentDisplay, w, StructureNotifyMask);
+
+ nxagentRootlessAddTopLevelWindow(pWin, w);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleReparentNotify: new top level window [%ld].\n", w);
+ fprintf(stderr, "nxagentHandleReparentNotify: reparented window [%ld].\n",
+ X -> xreparent.window);
+ #endif
+
+ result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ &root_return, &parent_return, &children_return, &nchildren_return);
+
+ if (result)
+ {
+ nxagentRootlessRestack(children_return, nchildren_return);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! Failed QueryTree request.\n");
+ #endif
+ }
+
+ if (result && nchildren_return)
+ {
+ XFree(children_return);
+ }
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleReparentNotify: Window at [%p] has been reparented to [%ld]"
+ " top level parent [%ld].\n", (void *) pWin, X -> xreparent.parent, w);
+ #endif
+
+ nxagentRootlessDelTopLevelWindow(pWin);
+ }
+ }
+
+ return 1;
+ }
+ else if (nxagentWMIsRunning == 1 && nxagentOption(Fullscreen) == 0 &&
+ nxagentOption(WMBorderWidth) == -1)
+ {
+ XlibWindow w;
+ XlibWindow rootReturn = 0;
+ XlibWindow parentReturn = 0;
+ XlibWindow junk;
+ XlibWindow *childrenReturn = NULL;
+ unsigned int nchildrenReturn = 0;
+ Status result;
+ XWindowAttributes attributes;
+ int x, y;
+ int xParent, yParent;
+
+ /*
+ * Calculate the absolute upper-left X e Y
+ */
+
+ if ((XGetWindowAttributes(nxagentDisplay, X -> xreparent.window,
+ &attributes) == 0))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! "
+ "XGetWindowAttributes failed.\n");
+ #endif
+
+ return 1;
+ }
+
+ x = attributes.x;
+ y = attributes.y;
+
+ XTranslateCoordinates(nxagentDisplay, X -> xreparent.window,
+ attributes.root, -attributes.border_width,
+ -attributes.border_width, &x, &y, &junk);
+
+ /*
+ * Calculate the parent X and parent Y.
+ */
+
+ w = X -> xreparent.parent;
+
+ if (w != DefaultRootWindow(nxagentDisplay))
+ {
+ do
+ {
+ result = XQueryTree(nxagentDisplay, w, &rootReturn, &parentReturn,
+ &childrenReturn, &nchildrenReturn);
+
+ if (parentReturn == rootReturn || parentReturn == 0 || result == 0)
+ {
+ break;
+ }
+
+ if (result == 1 && childrenReturn != NULL)
+ {
+ XFree(childrenReturn);
+ }
+
+ w = parentReturn;
+ }
+ while (True);
+
+ /*
+ * WM reparented. Find edge of the frame.
+ */
+
+ if (XGetWindowAttributes(nxagentDisplay, w, &attributes) == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleReparentNotify: WARNING! "
+ "XGetWindowAttributes failed for parent window.\n");
+ #endif
+
+ return 1;
+ }
+
+ xParent = attributes.x;
+ yParent = attributes.y;
+
+ /*
+ * Difference between Absolute X and Parent X gives thickness of side frame.
+ * Difference between Absolute Y and Parent Y gives thickness of title bar.
+ */
+
+ nxagentChangeOption(WMBorderWidth, (x - xParent));
+ nxagentChangeOption(WMTitleHeight, (y - yParent));
+ }
+ }
+
+ return 1;
+}
+
+void nxagentEnableKeyboardEvents()
+{
+ int i;
+ Mask mask;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ mask |= NXAGENT_KEYBOARD_EVENT_MASK;
+
+ nxagentSetDefaultEventMask(mask);
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask);
+ }
+
+ XkbSelectEvents(nxagentDisplay, XkbUseCoreKbd,
+ NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK,
+ NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK);
+}
+
+void nxagentDisableKeyboardEvents()
+{
+ int i;
+ Mask mask;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ mask &= ~NXAGENT_KEYBOARD_EVENT_MASK;
+
+ nxagentSetDefaultEventMask(mask);
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask);
+ }
+
+ XkbSelectEvents(nxagentDisplay, XkbUseCoreKbd, 0x0, 0x0);
+}
+
+void nxagentEnablePointerEvents()
+{
+ int i;
+ Mask mask;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ mask |= NXAGENT_POINTER_EVENT_MASK;
+
+ nxagentSetDefaultEventMask(mask);
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask);
+ }
+}
+
+void nxagentDisablePointerEvents()
+{
+ int i;
+ Mask mask;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ mask &= ~NXAGENT_POINTER_EVENT_MASK;
+
+ nxagentSetDefaultEventMask(mask);
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[i], mask);
+ }
+}
+
+void nxagentSendFakeKey(int key)
+{
+ xEvent fake;
+ Time now;
+
+ now = GetTimeInMillis();
+
+ memset(&fake, 0, sizeof(xEvent));
+ fake.u.u.type = KeyPress;
+ fake.u.u.detail = key;
+ fake.u.keyButtonPointer.time = now;
+
+ mieqEnqueue(&fake);
+
+ fake.u.u.type = KeyRelease;
+ fake.u.u.detail = key;
+ fake.u.keyButtonPointer.time = now;
+
+ mieqEnqueue(&fake);
+}
+
+int nxagentInitKeyboardState()
+{
+ XEvent X;
+
+ unsigned int modifiers;
+
+ XkbEvent *xkbev = (XkbEvent *) &X;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitKeyboardState: Initializing XKB state.\n");
+ #endif
+
+ memset(&X, 0, sizeof(XEvent));
+
+ XkbGetIndicatorState(nxagentDisplay, XkbUseCoreKbd, &modifiers);
+
+ xkbev -> state.locked_mods = 0x0;
+
+ if (modifiers & CAPSFLAG_IN_REPLY)
+ {
+ xkbev -> state.locked_mods |= CAPSFLAG_IN_EVENT;
+ }
+
+ if (modifiers & NUMFLAG_IN_REPLY)
+ {
+ xkbev -> state.locked_mods |= NUMFLAG_IN_EVENT;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitKeyboardState: Assuming XKB locked modifier bits [%x].\n",
+ xkbev -> state.locked_mods);
+ #endif
+
+ xkbev -> type = nxagentXkbInfo.EventBase + XkbEventCode;
+ xkbev -> any.xkb_type = XkbStateNotify;
+
+ nxagentHandleKeyboardEvent(&X);
+
+ return 1;
+}
+
+int nxagentWaitForResource(GetResourceFuncPtr pGetResource, PredicateFuncPtr pPredicate)
+{
+ int resource;
+
+ while ((resource = (*pGetResource)(nxagentDisplay)) == -1)
+ {
+ if (nxagentWaitEvents(nxagentDisplay, NULL) == -1)
+ {
+ return -1;
+ }
+
+ nxagentDispatchEvents(pPredicate);
+ }
+
+ return resource;
+}
+
+void nxagentGrabPointerAndKeyboard(XEvent *X)
+{
+ unsigned long now;
+
+ int resource;
+
+ int result;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGrabPointerAndKeyboard: Grabbing pointer and keyboard with event at [%p].\n",
+ (void *) X);
+ #endif
+
+ if (X != NULL)
+ {
+ now = X -> xcrossing.time;
+ }
+ else
+ {
+ now = CurrentTime;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to grab the keyboard in context [B1].\n");
+ #endif
+
+ result = XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow,
+ True, GrabModeAsync, GrabModeAsync, now);
+
+ if (result != GrabSuccess)
+ {
+ return;
+ }
+
+ /*
+ * The smart scheduler could be stopped while
+ * waiting for the reply. In this case we need
+ * to yield explicitly to avoid to be stuck in
+ * the dispatch loop forever.
+ */
+
+ isItTimeToYield = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to grab the pointer in context [B2].\n");
+ #endif
+
+ resource = nxagentWaitForResource(NXGetCollectGrabPointerResource,
+ nxagentCollectGrabPointerPredicate);
+
+ NXCollectGrabPointer(nxagentDisplay, resource,
+ nxagentFullscreenWindow, True, NXAGENT_POINTER_EVENT_MASK,
+ GrabModeAsync, GrabModeAsync, None, None, now);
+
+ /*
+ * This should not be needed.
+ *
+ * XGrabKey(nxagentDisplay, AnyKey, AnyModifier, nxagentFullscreenWindow,
+ * True, GrabModeAsync, GrabModeAsync);
+ */
+
+ if (X != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to force focus in context [B4].\n");
+ #endif
+
+ XSetInputFocus(nxagentDisplay, nxagentFullscreenWindow,
+ RevertToParent, now);
+ }
+}
+
+void nxagentUngrabPointerAndKeyboard(XEvent *X)
+{
+ unsigned long now;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUngrabPointerAndKeyboard: Ungrabbing pointer and keyboard with event at [%p].\n",
+ (void *) X);
+ #endif
+
+ if (X != NULL)
+ {
+ now = X -> xcrossing.time;
+ }
+ else
+ {
+ now = CurrentTime;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUngrabPointerAndKeyboard: Going to ungrab the keyboard in context [B5].\n");
+ #endif
+
+ XUngrabKeyboard(nxagentDisplay, now);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGrabPointerAndKeyboard: Going to ungrab the pointer in context [B6].\n");
+ #endif
+
+ XUngrabPointer(nxagentDisplay, now);
+}
+
+void nxagentDeactivatePointerGrab()
+{
+ GrabPtr grab = inputInfo.pointer -> grab;
+
+ XButtonEvent X;
+
+ if (grab)
+ {
+ X.type = ButtonRelease;
+ X.serial = 0;
+ X.send_event = FALSE;
+ X.time = currentTime.milliseconds;
+ X.display = nxagentDisplay;
+ X.window = nxagentWindow(grab -> window);
+ X.root = RootWindow(nxagentDisplay, 0);
+ X.subwindow = 0;
+ X.x = X.y = X.x_root = X.y_root = 0;
+ X.state = 0x100;
+ X.button = 1;
+ X.same_screen = TRUE;
+
+ XPutBackEvent(nxagentDisplay, (XEvent*)&X);
+ }
+}
+
+Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr)
+{
+ return (X -> xclient.window == 0 &&
+ X -> xclient.message_type == 0 &&
+ X -> xclient.format == 32 &&
+ X -> xclient.data.l[0] == NXCollectGrabPointerNotify);
+}
+
+void nxagentHandleCollectGrabPointerEvent(int resource)
+{
+ int status;
+
+ if (NXGetCollectedGrabPointer(nxagentDisplay, resource, &status) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleCollectGrabPointerEvent: PANIC! Failed to get GrabPointer "
+ "reply for resource [%d].\n", resource);
+ #endif
+ }
+}
+
+void nxagentHandleCollectPropertyEvent(XEvent *X)
+{
+ Window window;
+ Atom property;
+ Atom atomReturnType;
+ int resultFormat;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+ int result;
+ int resource;
+
+ resource = X -> xclient.data.l[1];
+
+ if (X -> xclient.data.l[2] == False)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentHandleCollectPropertyEvent: Failed to get reply data for client [%d].\n",
+ resource);
+ #endif
+
+ return;
+ }
+
+ if (resource == nxagentLastClipboardClient)
+ {
+ nxagentCollectPropertyEvent(resource);
+ }
+ else
+ {
+ result = NXGetCollectedProperty(nxagentDisplay,
+ resource,
+ &atomReturnType,
+ &resultFormat,
+ &ulReturnItems,
+ &ulReturnBytesLeft,
+ &pszReturnData);
+
+ if (result == True)
+ {
+ window = nxagentPropertyRequests[resource].window;
+ property = nxagentPropertyRequests[resource].property;
+
+ nxagentImportProperty(window, property, atomReturnType, resultFormat,
+ ulReturnItems, ulReturnBytesLeft, pszReturnData);
+ }
+
+ if (result == 0)
+ {
+ #ifdef DEBUG
+ fprintf (stderr, "nxagentHandleCollectPropertyEvent: Failed to get reply data for client [%d].\n",
+ resource);
+ #endif
+ }
+
+ if (pszReturnData != NULL)
+ {
+ XFree(pszReturnData);
+ }
+
+ return;
+ }
+}
+
+void nxagentSynchronizeExpose(void)
+{
+ WindowPtr pWin;
+
+ if (nxagentExposeQueue.length <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeExpose: PANIC! Called with nxagentExposeQueue.length [%d].\n",
+ nxagentExposeQueue.length);
+ #endif
+
+ return;
+ }
+
+ pWin = nxagentExposeQueueHead.pWindow;
+
+ if (pWin)
+ {
+ if ((nxagentExposeQueueHead.localRegion) != NullRegion)
+ {
+ RegionTranslate((nxagentExposeQueueHead.localRegion),
+ pWin -> drawable.x, pWin -> drawable.y);
+ }
+
+ if ((nxagentExposeQueueHead.remoteRegion) != NullRegion)
+ {
+ RegionTranslate((nxagentExposeQueueHead.remoteRegion),
+ pWin -> drawable.x, pWin -> drawable.y);
+ }
+
+ if ((nxagentExposeQueueHead.localRegion) != NullRegion &&
+ (nxagentExposeQueueHead.remoteRegion) != NullRegion)
+ {
+ RegionSubtract((nxagentExposeQueueHead.remoteRegion),
+ (nxagentExposeQueueHead.remoteRegion),
+ (nxagentExposeQueueHead.localRegion));
+
+ if (RegionNil(nxagentExposeQueueHead.remoteRegion) == 0 &&
+ ((pWin -> eventMask|wOtherEventMasks(pWin)) & ExposureMask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeExpose: Going to call miWindowExposures"
+ " for window [%ld] - rects [%ld].\n", nxagentWindow(pWin),
+ RegionNumRects(nxagentExposeQueueHead.remoteRegion));
+ #endif
+
+ miWindowExposures(pWin, nxagentExposeQueueHead.remoteRegion, NullRegion);
+ }
+ }
+ }
+
+ nxagentExposeQueueHead.pWindow = NULL;
+
+ if (nxagentExposeQueueHead.localRegion != NullRegion)
+ {
+ RegionDestroy(nxagentExposeQueueHead.localRegion);
+ }
+
+ nxagentExposeQueueHead.localRegion = NullRegion;
+
+ if (nxagentExposeQueueHead.remoteRegion != NullRegion)
+ {
+ RegionDestroy(nxagentExposeQueueHead.remoteRegion);
+ }
+
+ nxagentExposeQueueHead.remoteRegion = NullRegion;
+
+ nxagentExposeQueueHead.remoteRegionIsCompleted = False;
+
+ nxagentExposeQueue.start = (nxagentExposeQueue.start + 1) % EXPOSED_SIZE;
+
+ nxagentExposeQueue.length--;
+
+ return;
+}
+
+int nxagentLookupByWindow(WindowPtr pWin)
+{
+ int i;
+ int j;
+
+ for (j = 0; j < nxagentExposeQueue.length; j++)
+ {
+ i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
+
+ if (nxagentExposeQueue.exposures[i].pWindow == pWin &&
+ !nxagentExposeQueue.exposures[i].remoteRegionIsCompleted)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+void nxagentRemoveDuplicatedKeys(XEvent *X)
+{
+ _XQEvent *prev;
+ _XQEvent *qelt;
+
+ _XQEvent *qeltKeyRelease;
+ _XQEvent *prevKeyRelease;
+
+ KeyCode lastKeycode = X -> xkey.keycode;
+
+ qelt = nxagentDisplay -> head;
+
+ if (qelt == NULL)
+ {
+ #ifdef TEST
+
+ int more;
+
+ fprintf(stderr, "nxagentRemoveDuplicatedKeys: Trying to read more events "
+ "from the X server.\n");
+
+ more = nxagentReadEvents(nxagentDisplay);
+
+ if (more > 0)
+ {
+ fprintf(stderr, "nxagentRemoveDuplicatedKeys: Successfully read more events "
+ "from the X server.\n");
+ }
+
+ #else
+
+ nxagentReadEvents(nxagentDisplay);
+
+ #endif
+
+ qelt = nxagentDisplay -> head;
+ }
+
+ if (qelt != NULL)
+ {
+ prev = qeltKeyRelease = prevKeyRelease = NULL;
+
+ LockDisplay(nxagentDisplay);
+
+ while (qelt != NULL)
+ {
+ if (qelt -> event.type == KeyRelease ||
+ qelt -> event.type == KeyPress)
+ {
+ if (qelt -> event.xkey.keycode != lastKeycode ||
+ (qelt -> event.type == KeyPress && qeltKeyRelease == NULL) ||
+ (qelt -> event.type == KeyRelease && qeltKeyRelease != NULL))
+ {
+ break;
+ }
+
+ if (qelt -> event.type == KeyRelease)
+ {
+ prevKeyRelease = prev;
+
+ qeltKeyRelease = qelt;
+ }
+ else if (qelt -> event.type == KeyPress)
+ {
+ _XDeq(nxagentDisplay, prev, qelt);
+
+ qelt = prev -> next;
+
+ if (prev == qeltKeyRelease)
+ {
+ prev = prevKeyRelease;
+ }
+
+ _XDeq(nxagentDisplay, prevKeyRelease, qeltKeyRelease);
+
+ qeltKeyRelease = prevKeyRelease = NULL;
+
+ continue;
+ }
+ }
+
+ prev = qelt;
+
+ qelt = qelt -> next;
+ }
+
+ UnlockDisplay(nxagentDisplay);
+ }
+}
+
+void nxagentInitRemoteExposeRegion(void)
+{
+ if (nxagentRemoteExposeRegion == NULL)
+ {
+ nxagentRemoteExposeRegion = RegionCreate(NULL, 1);
+
+ if (nxagentRemoteExposeRegion == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentInitRemoteExposeRegion: PANIC! Failed to create expose region.\n");
+ #endif
+ }
+ }
+}
+
+void nxagentForwardRemoteExpose(void)
+{
+ if (RegionNotEmpty(nxagentRemoteExposeRegion))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentForwardRemoteExpose: Going to forward events.\n");
+ #endif
+
+ TraverseTree(screenInfo.screens[0]->root, nxagentClipAndSendExpose, (void *)nxagentRemoteExposeRegion);
+
+ /*
+ * Now this region should be empty.
+ */
+
+ RegionEmpty(nxagentRemoteExposeRegion);
+ }
+}
+
+void nxagentAddRectToRemoteExposeRegion(BoxPtr rect)
+{
+ RegionRec exposeRegion;
+
+ if (nxagentRemoteExposeRegion == NULL)
+ {
+ return;
+ }
+
+ RegionInit(&exposeRegion, rect, 1);
+
+ RegionUnion(nxagentRemoteExposeRegion,
+ nxagentRemoteExposeRegion, &exposeRegion);
+
+ RegionUninit(&exposeRegion);
+}
+
+int nxagentClipAndSendExpose(WindowPtr pWin, void * ptr)
+{
+ RegionPtr exposeRgn;
+ RegionPtr remoteExposeRgn;
+
+ #ifdef DEBUG
+ BoxRec box;
+
+ fprintf(stderr, "nxagentClipAndSendExpose: Called.\n");
+ #endif
+
+ remoteExposeRgn = (RegionRec *) ptr;
+
+ if (pWin -> drawable.class != InputOnly)
+ {
+ exposeRgn = RegionCreate(NULL, 1);
+
+ #ifdef DEBUG
+ box = *RegionExtents(remoteExposeRgn);
+
+ fprintf(stderr, "nxagentClipAndSendExpose: Root expose extents: [%d] [%d] [%d] [%d].\n",
+ box.x1, box.y1, box.x2, box.y2);
+
+ box = *RegionExtents(&pWin -> clipList);
+
+ fprintf(stderr, "nxagentClipAndSendExpose: Clip list extents for window at [%p]: [%d] [%d] [%d] [%d].\n",
+ pWin, box.x1, box.y1, box.x2, box.y2);
+ #endif
+
+ RegionIntersect(exposeRgn, remoteExposeRgn, &pWin -> clipList);
+
+ if (RegionNotEmpty(exposeRgn))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClipAndSendExpose: Forwarding expose to window at [%p] pWin.\n",
+ pWin);
+ #endif
+
+ /*
+ * The miWindowExposures() clears out the
+ * region parameters, so the subtract ope-
+ * ration must be done before calling it.
+ */
+
+ RegionSubtract(remoteExposeRgn, remoteExposeRgn, exposeRgn);
+
+ miWindowExposures(pWin, exposeRgn, NullRegion);
+ }
+
+ RegionDestroy(exposeRgn);
+ }
+
+ if (RegionNotEmpty(remoteExposeRgn))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClipAndSendExpose: Region not empty. Walk children.\n");
+ #endif
+
+ return WT_WALKCHILDREN;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentClipAndSendExpose: Region empty. Stop walking.\n");
+ #endif
+
+ return WT_STOPWALKING;
+ }
+}
+
+int nxagentUserInput(void *p)
+{
+ int result = 0;
+
+ /*
+ * This function is used as callback in
+ * the polling handler of agent in shadow
+ * mode. When inside the polling loop the
+ * handlers are never called, so we have
+ * to dispatch enqueued events to eventu-
+ * ally change the nxagentInputEvent sta-
+ * tus.
+ */
+
+ if (nxagentOption(Shadow) == 1 &&
+ nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ nxagentDispatchEvents(NULL);
+ }
+
+ if (nxagentInputEvent == 1)
+ {
+ nxagentInputEvent = 0;
+
+ result = 1;
+ }
+
+ /*
+ * The agent working in shadow mode synch-
+ * ronizes the remote X server even if a
+ * button/key is not released (i.e. when
+ * scrolling a long browser's page), in
+ * order to update the screen smoothly.
+ */
+
+ if (nxagentOption(Shadow) == 1)
+ {
+ return result;
+ }
+
+ if (result == 0)
+ {
+ /*
+ * If there is at least one button/key down,
+ * we are receiving an input. This is not a
+ * condition to break a synchronization loop
+ * if there is enough bandwidth.
+ */
+
+ if (nxagentCongestion > 0 &&
+ (inputInfo.pointer -> button -> buttonsDown > 0 ||
+ nxagentKeyDown > 0))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentUserInput: Buttons [%d] Keys [%d].\n",
+ inputInfo.pointer -> button -> buttonsDown, nxagentKeyDown);
+ #endif
+
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+int nxagentHandleRRScreenChangeNotify(XEvent *X)
+{
+ XRRScreenChangeNotifyEvent *Xr;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleRRScreenChangeNotify called.\n");
+ #endif
+
+ Xr = (XRRScreenChangeNotifyEvent *) X;
+
+ nxagentResizeScreen(screenInfo.screens[DefaultScreen(nxagentDisplay)], Xr -> width, Xr -> height,
+ Xr -> mwidth, Xr -> mheight);
+
+ nxagentShadowCreateMainWindow(screenInfo.screens[DefaultScreen(nxagentDisplay)], screenInfo.screens[0]->root,
+ Xr -> width, Xr -> height);
+
+ nxagentShadowSetWindowsSize();
+
+ return 1;
+}
+
+/*
+ * Returns true if there is any event waiting to
+ * be dispatched. This function is critical for
+ * the performance because it is called very,
+ * very often. It must also handle the case when
+ * the display is down. The display descriptor,
+ * in fact, may have been reused by some other
+ * client.
+ */
+
+int nxagentPendingEvents(Display *dpy)
+{
+ if (_XGetIOError(dpy) != 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPendingEvents: Returning error with display down.\n");
+ #endif
+
+ return -1;
+ }
+ else if (XQLength(dpy) > 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPendingEvents: Returning true with [%d] events queued.\n",
+ XQLength(dpy));
+ #endif
+
+ return 1;
+ }
+ else
+ {
+ int result;
+ int readable;
+
+ result = NXTransReadable(dpy -> fd, &readable);
+
+ if (result == 0)
+ {
+ if (readable > 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPendingEvents: Returning true with [%d] bytes readable.\n",
+ readable);
+ #endif
+
+ return 1;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPendingEvents: Returning false with [%d] bytes readable.\n",
+ readable);
+ #endif
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPendingEvents: WARNING! Error detected on the X display.\n");
+ #endif
+
+ NXForceDisplayError(dpy);
+
+ return -1;
+ }
+}
+
+/*
+ * Blocks until an event becomes
+ * available.
+ */
+
+int nxagentWaitEvents(Display *dpy, struct timeval *tm)
+{
+ XEvent ev;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWaitEvents called.\n");
+ #endif
+
+ NXFlushDisplay(dpy, NXFlushLink);
+
+ /*
+ * If the transport is not running we
+ * have to rely on Xlib to wait for an
+ * event. In this case the timeout is
+ * ignored.
+ */
+
+ if (NXTransRunning(NX_FD_ANY) == 1)
+ {
+ NXTransContinue(tm);
+ }
+ else
+ {
+ XPeekEvent(dpy, &ev);
+ }
+
+ /*
+ * Check if we encountered a display
+ * error. If we did, wait for the
+ * time requested by the caller.
+ */
+
+ if (NXDisplayError(dpy) == 1)
+ {
+ if (tm != NULL)
+ {
+ usleep(tm -> tv_sec * 1000 * 1000 +
+ tm -> tv_usec);
+ }
+
+ return -1;
+ }
+
+ return 1;
+}
+
+#ifdef NX_DEBUG_INPUT
+
+void nxagentDumpInputInfo(void)
+{
+ fprintf(stderr, "Dumping input info ON.\n");
+}
+
+void nxagentGuessDumpInputInfo(ClientPtr client, Atom property, char *data)
+{
+ if (strcmp(validateString(NameForAtom(property)), "NX_DEBUG_INPUT") == 0)
+ {
+ if (*data != 0)
+ {
+ nxagentDebugInput = 1;
+ }
+ else
+ {
+ nxagentDebugInput = 0;
+ }
+ }
+}
+
+void nxagentDeactivateInputDevicesGrabs()
+{
+ fprintf(stderr, "Info: Deactivating input devices grabs.\n");
+
+ if (inputInfo.pointer -> grab)
+ {
+ (*inputInfo.pointer -> DeactivateGrab)(inputInfo.pointer);
+ }
+
+ if (inputInfo.keyboard -> grab)
+ {
+ (*inputInfo.keyboard -> DeactivateGrab)(inputInfo.keyboard);
+ }
+}
+
+static const char *nxagentGrabStateToString(int state)
+{
+ switch (state)
+ {
+ case 0:
+ return "NOT_GRABBED";
+ case 1:
+ return "THAWED";
+ case 2:
+ return "THAWED_BOTH";
+ case 3:
+ return "FREEZE_NEXT_EVENT";
+ case 4:
+ return "FREEZE_BOTH_NEXT_EVENT";
+ case 5:
+ return "FROZEN_NO_EVENT";
+ case 6:
+ return "FROZEN_WITH_EVENT";
+ case 7:
+ return "THAW_OTHERS";
+ default:
+ return "unknown state";
+ }
+}
+
+void nxagentDumpInputDevicesState(void)
+{
+ int i, k;
+ int mask = 1;
+ CARD8 val;
+ DeviceIntPtr dev;
+ GrabPtr grab;
+ WindowPtr pWin = NULL;
+
+ fprintf(stderr, "\n*** Dump input devices state: BEGIN ***"
+ "\nKeys down:");
+
+ dev = inputInfo.keyboard;
+
+ for (i = 0; i < DOWN_LENGTH; i++)
+ {
+ val = dev -> key -> down[i];
+
+ if (val != 0)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ if (val & (mask << k))
+ {
+ fprintf(stderr, "\n\t[%d] [%s]", i * 8 + k,
+ XKeysymToString(XKeycodeToKeysym(nxagentDisplay, i * 8 + k, 0)));
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "\nKeyboard device state: \n\tdevice [%p]\n\tlast grab time [%lu]"
+ "\n\tfrozen [%s]\n\tstate [%s]\n\tother [%p]\n\tevent count [%d]"
+ "\n\tfrom passive grab [%s]\n\tactivating key [%d]", dev,
+ dev -> grabTime.milliseconds, dev -> sync.frozen ? "Yes": "No",
+ nxagentGrabStateToString(dev -> sync.state),
+ dev -> sync.other, dev -> sync.evcount,
+ dev -> fromPassiveGrab ? "Yes" : "No",
+ dev -> activatingKey);
+
+ grab = dev -> grab;
+
+ if (grab)
+ {
+ fprintf(stderr, "\nKeyboard grab state: \n\twindow pointer [%p]"
+ "\n\towner events flag [%s]\n\tgrab mode [%s]",
+ grab -> window, grab -> ownerEvents ? "True" : "False",
+ grab -> keyboardMode ? "asynchronous" : "synchronous");
+
+ /*
+ * Passive grabs.
+ */
+
+ pWin = grab -> window;
+ grab = wPassiveGrabs(pWin);
+
+ while (grab)
+ {
+ fprintf(stderr, "\nPassive grab state: \n\tdevice [%p]\n\towner events flag [%s]"
+ "\n\tpointer grab mode [%s]\n\tkeyboard grab mode [%s]\n\tevent type [%d]"
+ "\n\tmodifiers [%x]\n\tbutton/key [%u]\n\tevent mask [%lx]",
+ grab -> device, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous",
+ grab -> keyboardMode ? "asynchronous" : "synchronous",
+ grab -> type, grab -> modifiersDetail.exact,
+ grab -> detail.exact, grab -> eventMask);
+
+ grab = grab -> next;
+ }
+ }
+
+ fprintf(stderr, "\nButtons down:");
+
+ dev = inputInfo.pointer;
+
+ for (i = 0; i < DOWN_LENGTH; i++)
+ {
+ val = dev -> button -> down[i];
+
+ if (val != 0)
+ {
+ for (k = 0; k < 8; k++)
+ {
+ if (val & (mask << k))
+ {
+ fprintf(stderr, "\n\t[%d]", i * 8 + k);
+ }
+ }
+ }
+ }
+
+ fprintf(stderr, "\nPointer device state: \n\tdevice [%p]\n\tlast grab time [%lu]"
+ "\n\tfrozen [%s]\n\tstate [%s]\n\tother [%p]\n\tevent count [%d]"
+ "\n\tfrom passive grab [%s]\n\tactivating button [%d]", dev,
+ dev -> grabTime.milliseconds, dev -> sync.frozen ? "Yes" : "No",
+ nxagentGrabStateToString(dev -> sync.state),
+ dev -> sync.other, dev -> sync.evcount,
+ dev -> fromPassiveGrab ? "Yes" : "No",
+ dev -> activatingKey);
+
+ grab = dev -> grab;
+
+ if (grab)
+ {
+ fprintf(stderr, "\nPointer grab state: \n\twindow pointer [%p]"
+ "\n\towner events flag [%s]\n\tgrab mode [%s]",
+ grab -> window, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous");
+
+ if (grab -> window != pWin)
+ {
+ /*
+ * Passive grabs.
+ */
+
+ grab = wPassiveGrabs(grab -> window);
+
+ while (grab)
+ {
+ fprintf(stderr, "\nPassive grab state: \n\tdevice [%p]\n\towner events flag [%s]"
+ "\n\tpointer grab mode [%s]\n\tkeyboard grab mode [%s]\n\tevent type [%d]"
+ "\n\tmodifiers [%x]\n\tbutton/key [%u]\n\tevent mask [%lx]",
+ grab -> device, grab -> ownerEvents ? "True" : "False",
+ grab -> pointerMode ? "asynchronous" : "synchronous",
+ grab -> keyboardMode ? "asynchronous" : "synchronous",
+ grab -> type, grab -> modifiersDetail.exact,
+ grab -> detail.exact, grab -> eventMask);
+
+ grab = grab -> next;
+ }
+ }
+ }
+
+ fprintf(stderr, "\n*** Dump input devices state: FINISH ***\n");
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Events.h b/nx-X11/programs/Xserver/hw/nxagent/Events.h
new file mode 100644
index 000000000..7d313c331
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Events.h
@@ -0,0 +1,238 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Events_H__
+#define __Events_H__
+
+#include <nx-X11/Xmd.h>
+
+#define ProcessedExpose (LASTEvent + 1)
+#define ProcessedNotify (LASTEvent + 2)
+
+#define EXPOSED_SIZE 256
+
+enum HandleEventResult
+{
+ doNothing = 0,
+ doMinimize,
+ doDebugTree,
+ doCloseSession,
+ doStartKbd,
+ doSwitchFullscreen,
+ doSwitchAllScreens,
+ doViewportMoveUp,
+ doViewportMoveLeft,
+ doViewportMoveRight,
+ doViewportMoveDown,
+ doViewportLeft,
+ doViewportUp,
+ doViewportRight,
+ doViewportDown,
+ doSwitchResizeMode,
+ doSwitchDeferMode
+};
+
+extern CARD32 nxagentLastEventTime;
+
+/*
+ * Manage incoming events.
+ */
+
+typedef Bool (*PredicateFuncPtr)(Display*, XEvent*, XPointer);
+
+extern void nxagentDispatchEvents(PredicateFuncPtr);
+
+typedef int (*GetResourceFuncPtr)(Display*);
+
+int nxagentWaitForResource(GetResourceFuncPtr, PredicateFuncPtr);
+
+Bool nxagentCollectGrabPointerPredicate(Display *display, XEvent *X, XPointer ptr);
+
+int nxagentInputEventPredicate(Display *display, XEvent *event, XPointer parameter);
+
+/*
+ * Enable and disable notification of
+ * remote X server events.
+ */
+
+extern void nxagentEnableKeyboardEvents(void);
+extern void nxagentEnablePointerEvents(void);
+
+extern void nxagentDisableKeyboardEvents(void);
+extern void nxagentDisablePointerEvents(void);
+
+/*
+ * Manage default event mask.
+ */
+
+extern void nxagentInitDefaultEventMask(void);
+extern void nxagentGetDefaultEventMask(Mask *mask_return);
+extern void nxagentSetDefaultEventMask(Mask mask);
+extern void nxagentGetEventMask(WindowPtr pWin, Mask *mask_return);
+
+/*
+ * Bring keyboard device in known state. It needs
+ * a round-trip so it only gets called if a pre-
+ * vious XKB event did not implicitly initialized
+ * the internal state. This is unlikely to happen.
+ */
+
+extern int nxagentInitKeyboardState(void);
+
+/*
+ * Update the keyboard state according
+ * to focus and XKB events received
+ * from the remote X server.
+ */
+
+extern int nxagentHandleKeyboardEvent(XEvent *X);
+
+/*
+ * Handle sync and karma messages and
+ * other notification event coming
+ * from proxy.
+ */
+
+extern int nxagentHandleProxyEvent(XEvent *X);
+
+/*
+ * Other functions providing the ad-hoc
+ * handling of the remote X events.
+ */
+
+extern int nxagentHandleExposeEvent(XEvent *X);
+extern int nxagentHandleGraphicsExposeEvent(XEvent *X);
+extern int nxagentHandleClientMessageEvent(XEvent *X, enum HandleEventResult*);
+extern int nxagentHandlePropertyNotify(XEvent *X);
+extern int nxagentHandleKeyPress(XEvent *X, enum HandleEventResult*);
+extern int nxagentHandleReparentNotify(XEvent *X);
+extern int nxagentHandleConfigureNotify(XEvent *X);
+extern int nxagentHandleXFixesSelectionNotify(XEvent *X);
+
+/*
+ * Send a fake keystroke to the remote
+ * X server.
+ */
+
+extern void nxagentSendFakeKey(int key);
+
+/*
+ * Called to manage grab of pointer and
+ * keyboard when running in fullscreen
+ * mode.
+ */
+
+extern void nxagentGrabPointerAndKeyboard(XEvent *X);
+extern void nxagentUngrabPointerAndKeyboard(XEvent *X);
+
+extern void nxagentDeactivatePointerGrab(void);
+
+/*
+ * Handle the selection property received
+ * in the event loop.
+ */
+
+void nxagentCollectPropertyEvent(int resource);
+
+/*
+ * Synchronize expose events between agent and
+ * the real X server.
+ */
+
+typedef struct _ExposuresRec
+{
+ WindowPtr pWindow;
+ RegionPtr localRegion;
+ RegionPtr remoteRegion;
+ Bool remoteRegionIsCompleted;
+ int serial;
+ int synchronize;
+
+} ExposuresRec;
+
+extern RegionPtr nxagentRemoteExposeRegion;
+
+typedef struct _ExposeQueue
+{
+ unsigned int start;
+ int length;
+ ExposuresRec exposures[EXPOSED_SIZE];
+} ExposeQueue;
+
+extern void nxagentSynchronizeExpose(void);
+extern int nxagentLookupByWindow(WindowPtr pWin);
+extern void nxagentUpdateExposeArray(void);
+
+extern ExposeQueue nxagentExposeQueue;
+
+/*
+ * Handle the split related notifications.
+ */
+
+int nxagentWaitSplitEvent(int resource);
+
+void nxagentHandleNoSplitEvent(int resource);
+void nxagentHandleStartSplitEvent(int resource);
+void nxagentHandleCommitSplitEvent(int resource, int request, int position);
+void nxagentHandleEndSplitEvent(int resource);
+void nxagentHandleEmptySplitEvent(void);
+
+void nxagentInitRemoteExposeRegion(void);
+void nxagentAddRectToRemoteExposeRegion(BoxPtr);
+
+extern int nxagentUserInput(void *p);
+
+/*
+* We have to check these before launching the terminate
+ * dialog in rootless mode.
+ */
+
+extern Bool nxagentLastWindowDestroyed;
+extern Time nxagentLastWindowDestroyedTime;
+
+/*
+ * Set this flag if an user input event is received.
+ */
+
+extern int nxagentInputEvent;
+
+/*
+ * Event-handling utilities.
+ */
+
+Bool nxagentPendingEvents(Display *dpy);
+
+#define nxagentQueuedEvents(display) \
+ XQLength((display))
+
+#define nxagentReadEvents(display) \
+ XEventsQueued((display), QueuedAfterReading)
+
+#define nxagentCheckEvents(display, event, predicate, argument) \
+ XCheckIfEventNoFlush((display), (event), (predicate), (argument))
+
+int nxagentWaitEvents(Display *, struct timeval *);
+
+#endif /* __Events_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Extensions.c b/nx-X11/programs/Xserver/hw/nxagent/Extensions.c
new file mode 100644
index 000000000..d9db1a8aa
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.c
@@ -0,0 +1,470 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "micmap.h"
+#include "scrnintstr.h"
+#include "../../randr/randrstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Options.h"
+#include "Extensions.h"
+#include "Windows.h"
+
+void GlxExtensionInit(void);
+void GlxWrapInitVisuals(void *procPtr);
+
+static int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width,
+ CARD16 height, CARD32 mmWidth,
+ CARD32 mmHeight);
+
+static int nxagentRandRInitSizes(ScreenPtr pScreen);
+
+#if RANDR_14_INTERFACE
+static Bool
+nxagentRandRReplaceScanoutPixmap(DrawablePtr pDrawable,
+ PixmapPtr pPixmap,
+ Bool enable);
+#endif
+
+#if RANDR_13_INTERFACE
+static Bool
+nxagentRandROutputGetProperty(ScreenPtr pScreen,
+ RROutputPtr output,
+ Atom property);
+static Bool
+nxagentRandRGetPanning(ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border);
+static Bool
+nxagentRandRSetPanning(ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border);
+#endif
+
+#if RANDR_12_INTERFACE
+static Bool nxagentRandRCrtcSet (ScreenPtr pScreen, RRCrtcPtr crtc,
+ RRModePtr mode, int x, int y,
+ Rotation rotation, int numOutputs,
+ RROutputPtr *outputs);
+#endif
+
+#ifdef __DARWIN__
+
+void DarwinHandleGUI(int argc, char *argv[])
+{
+}
+
+void DarwinGlxExtensionInit()
+{
+ GlxExtensionInit();
+}
+
+void DarwinGlxWrapInitVisuals(void *procPtr)
+{
+ GlxWrapInitVisuals(procPtr);
+}
+
+#endif
+
+void nxagentInitGlxExtension(VisualPtr *visuals, DepthPtr *depths,
+ int *numVisuals, int *numDepths, int *rootDepth,
+ VisualID *defaultVisual)
+{
+ miInitVisualsProcPtr initVisuals;
+
+ /*
+ * Initialize the visuals to use the GLX extension.
+ */
+
+ initVisuals = NULL;
+
+ GlxWrapInitVisuals(&initVisuals);
+
+ if (initVisuals(visuals, depths, numVisuals, numDepths,
+ rootDepth, defaultVisual, 0, 0, 0) == 0)
+ {
+ fprintf(stderr, "Warning: Failed to initialize the GLX extension.\n");
+ }
+}
+
+void nxagentInitRandRExtension(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pRandRScrPriv;
+
+ if (RRScreenInit(pScreen) == 0)
+ {
+ fprintf(stderr, "Warning: Failed to initialize the RandR extension.\n");
+ }
+
+
+ /* FIXME: do we need this at all with the new rand/xinerama stuff? */
+ nxagentRandRInitSizes(pScreen);
+
+ /*
+ * RRScreenInit sets these pointers to NULL,
+ * so requiring the server to set up its own
+ * replacements.
+ */
+
+ pRandRScrPriv = rrGetScrPriv(pScreen);
+
+ pRandRScrPriv -> rrGetInfo = nxagentRandRGetInfo;
+
+ #if RANDR_15_INTERFACE
+ /* nothing to be assigned here, so far */
+ #endif
+
+ #if RANDR_14_INTERFACE
+ /* no pixmap sharing in nx-X11 */
+ pScreen->ReplaceScanoutPixmap = nxagentRandRReplaceScanoutPixmap;
+ pRandRScrPriv -> rrCrtcSetScanoutPixmap = NULL;
+
+ /* only fake provider support in nx-X11, so far */
+ pRandRScrPriv -> provider = RRProviderCreate(pScreen, "default", 7);
+ pRandRScrPriv -> rrProviderSetOutputSource = NULL;
+ pRandRScrPriv -> rrProviderSetOffloadSink = NULL;
+ pRandRScrPriv -> rrProviderGetProperty = NULL;
+ pRandRScrPriv -> rrProviderSetProperty = NULL;
+ #endif
+
+ #if RANDR_13_INTERFACE
+ pRandRScrPriv -> rrOutputGetProperty = nxagentRandROutputGetProperty;
+ pRandRScrPriv -> rrGetPanning = nxagentRandRGetPanning;
+ pRandRScrPriv -> rrSetPanning = nxagentRandRSetPanning;
+ #endif
+
+ #if RANDR_12_INTERFACE
+ pRandRScrPriv -> rrScreenSetSize = nxagentRandRScreenSetSize;
+ pRandRScrPriv -> rrCrtcSet = nxagentRandRCrtcSet;
+ #endif
+
+ #if RANDR_10_INTERFACE
+ pRandRScrPriv -> rrSetConfig = nxagentRandRSetConfig;
+ #endif
+}
+
+#if RANDR_14_INTERFACE
+static Bool
+nxagentRandRReplaceScanoutPixmap(DrawablePtr pDrawable,
+ PixmapPtr pPixmap,
+ Bool enable)
+{
+ /* FALSE means: not supported */
+#ifdef DEBUG
+ fprintf(stderr, "nxagentRandRReplaceScanoutPixmap: NX's RANDR does not support scan-out pixmaps.\n");
+#endif
+ return FALSE;
+}
+#endif
+
+#if RANDR_13_INTERFACE
+static Bool
+nxagentRandROutputGetProperty(ScreenPtr pScreen,
+ RROutputPtr output,
+ Atom property)
+{
+ /* FALSE means: no property required to be modified on the fly here */
+ return FALSE;
+}
+
+static Bool
+nxagentRandRGetPanning(ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border)
+{
+ /* FALSE means: no, panning is not supported at the moment...
+ * Panning requires several modes to be available for
+ * the NX<n> output(s).
+ *
+ * FIXME: Add more modes per output than the current window size.
+ * At least when in fullscreen mode.
+ */
+#ifdef DEBUG
+ fprintf(stderr, "nxagentRandRGetPanning: RANDR Panning is currently not supported.\n");
+#endif
+ return FALSE;
+}
+
+static Bool
+nxagentRandRSetPanning(ScreenPtr pScrn,
+ RRCrtcPtr crtc,
+ BoxPtr totalArea,
+ BoxPtr trackingArea,
+ INT16 *border)
+{
+ /* FALSE means: no, panning is not supported at the moment...
+ * Panning requires several modes to be available for
+ * the NX<n> output(s).
+ *
+ * FIXME: Add more modes per output than the current window size.
+ * At least when in fullscreen mode.
+ */
+#ifdef DEBUG
+ fprintf(stderr, "nxagentRandRSetPanning: RANDR Panning is currently not supported.\n");
+#endif
+ return FALSE;
+}
+#endif
+
+#if RANDR_12_INTERFACE
+/*
+ * Request that the Crtc be reconfigured
+ */
+
+static Bool
+nxagentRandRCrtcSet (ScreenPtr pScreen,
+ RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutputs, outputs);
+}
+#endif
+
+
+int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations)
+{
+ /*
+ * Rotation is not supported.
+ */
+
+ *pRotations = RR_Rotate_0;
+
+ return 1;
+}
+
+static int nxagentRandRInitSizes(ScreenPtr pScreen)
+{
+ RRScreenSizePtr pSize;
+
+ int width;
+ int height;
+
+ int maxWidth;
+ int maxHeight;
+
+/*
+ int w[] = {0, 160, 320, 640, 800, 1024, 1152, 1280, 1280, 1280, 1280, 1280,
+ 1280, 1360, 1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
+ int h[] = {0, 120, 240, 480, 600, 768, 864, 600, 720, 800, 854, 960,
+ 1024, 768, 900, 900, 1200, 1050, 1080, 1200, 0, 0};
+*/
+ int w[] = {0, 320, 640, 640, 800, 800, 1024, 1024, 1152, 1280, 1280, 1280, 1360,
+ 1440, 1600, 1600, 1680, 1920, 1920, 0, 0};
+ int h[] = {0, 240, 360, 480, 480, 600, 600, 768, 864, 720, 800, 1024, 768,
+ 900, 900, 1200, 1050, 1080, 1200, 0, 0};
+
+ int i;
+ int nSizes;
+
+ int mmWidth;
+ int mmHeight;
+
+ /*
+ * Register all the supported sizes. The third
+ * parameter is the refresh rate.
+ */
+
+ maxWidth = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ maxHeight = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+
+ nSizes = sizeof w / sizeof(int);
+
+ /*
+ * Add current and max sizes.
+ */
+
+ w[nSizes - 1] = pScreen -> width;
+ h[nSizes - 1] = pScreen -> height;
+
+ w[nSizes - 2] = maxWidth;
+ h[nSizes - 2] = maxHeight;
+
+ /*
+ * Compute default size.
+ */
+
+ w[0] = w[2];
+ h[0] = h[2];
+
+ for (i = 3; i < nSizes - 1; i++)
+ {
+ if ((w[i] <= maxWidth * 3 / 4) &&
+ (h[i] <= maxHeight * 3 / 4) &&
+ (w[i] >= w[0]) &&
+ (h[i] >= h[0]))
+ {
+ w[0] = w[i];
+ h[0] = h[i];
+ }
+ }
+
+ for (i = 0; i < nSizes; i++)
+ {
+ width = w[i];
+ height = h[i];
+
+ mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmWidth < 1)
+ {
+ mmWidth = 1;
+ }
+
+ mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmHeight < 1)
+ {
+ mmHeight = 1;
+ }
+
+ pSize = RRRegisterSize(pScreen, width, height, mmWidth, mmHeight);
+
+ if (pSize == NULL)
+ {
+ return 0;
+ }
+
+ RRRegisterRate (pScreen, pSize, 60);
+ }
+
+ RRSetCurrentConfig(pScreen, RR_Rotate_0, 60, pSize);
+
+ return 1;
+}
+
+#if RANDR_10_INTERFACE
+
+int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
+ int rate, RRScreenSizePtr pSize)
+{
+ int r;
+
+ UpdateCurrentTime();
+
+ /*
+ * Whatever size is OK for us.
+ */
+
+ r = nxagentResizeScreen(pScreen, pSize -> width, pSize -> height,
+ pSize -> mmWidth, pSize -> mmHeight);
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ return r;
+}
+
+#endif
+
+#if RANDR_12_INTERFACE
+
+void nxagentRandRSetWindowsSize(int width, int height)
+{
+ if (width == 0)
+ {
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ width = nxagentOption(Width);
+ }
+ }
+
+ if (height == 0)
+ {
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ height = nxagentOption(Height);
+ }
+ }
+
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0], width, height);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0, width,
+ height);
+ }
+}
+
+int nxagentRandRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ int result;
+
+ UpdateCurrentTime();
+
+ if (nxagentOption(DesktopResize) == 1 &&
+ (nxagentOption(Fullscreen) == 1 ||
+ width > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) ||
+ height > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))))
+ {
+ if (nxagentOption(ClientOs) != ClientOsWinnt
+ /*&& nxagentOption(ClientOs) != ClientNXPlayer*/)
+ {
+ nxagentChangeOption(DesktopResize, 0);
+ }
+ }
+
+ if (nxagentOption(DesktopResize) == 1 && nxagentOption(Fullscreen) == 0 &&
+ nxagentOption(AllScreens) == 0)
+ {
+ nxagentChangeOption(Width, width);
+ nxagentChangeOption(Height, height);
+ }
+
+ result = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
+
+ if (result == 1 && nxagentOption(DesktopResize) == 1 &&
+ nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0)
+ {
+ nxagentRandRSetWindowsSize(width, height);
+ nxagentSetWMNormalHints(pScreen -> myNum);
+ }
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ return result;
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Extensions.h b/nx-X11/programs/Xserver/hw/nxagent/Extensions.h
new file mode 100644
index 000000000..9b3672f5a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Extensions.h
@@ -0,0 +1,43 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Initialize the additional extensions.
+ */
+
+void nxagentInitGlxExtension(VisualPtr *visuals, DepthPtr *depths,
+ int *numVisuals, int *numDepths, int *rootDepth,
+ VisualID *defaultVisual);
+
+void nxagentInitRandRExtension(ScreenPtr pScreen);
+
+/*
+ * Basic interface to the RandR extension.
+ */
+
+int nxagentRandRGetInfo(ScreenPtr pScreen, Rotation *pRotations);
+
+int nxagentRandRSetConfig(ScreenPtr pScreen, Rotation rotation,
+ int rate, RRScreenSizePtr pSize);
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Font.c b/nx-X11/programs/Xserver/hw/nxagent/Font.c
new file mode 100644
index 000000000..f9c682765
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Font.c
@@ -0,0 +1,1864 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "scrnintstr.h"
+#include "dixstruct.h"
+#include <X11/fonts/font.h>
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "misc.h"
+#include "miscstruct.h"
+#include "opaque.h"
+
+#include "Agent.h"
+
+#include "Display.h"
+#include "Font.h"
+#include "Error.h"
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include "resource.h"
+#include "Reconnect.h"
+
+#include "Args.h"
+#include "Utils.h"
+
+#include "compext/Compext.h"
+#include <nx/NXalert.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define NXAGENT_DEFAULT_FONT_DIR "/usr/share/nx/fonts"
+#define NXAGENT_ALTERNATE_FONT_DIR "/usr/share/X11/fonts"
+#define NXAGENT_ALTERNATE_FONT_DIR_2 "/usr/share/fonts/X11"
+#define NXAGENT_ALTERNATE_FONT_DIR_3 "/usr/X11R6/lib/X11/fonts"
+
+#define NXAGENT_DEFAULT_FONT_PATH \
+"/usr/share/nx/fonts/misc/,/usr/share/nx/fonts/Speedo/,\
+/usr/share/nx/fonts/Type1/,/usr/share/nx/fonts/75dpi/,\
+/usr/share/nx/fonts/100dpi/,/usr/share/nx/fonts/TTF/"
+
+#define NXAGENT_ALTERNATE_FONT_PATH \
+"/usr/share/X11/fonts/misc/,/usr/share/X11/fonts/Speedo/,\
+/usr/share/X11/fonts/Type1/,/usr/share/X11/fonts/75dpi/,\
+/usr/share/X11/fonts/100dpi/,/usr/share/X11/fonts/TTF/"
+
+#define NXAGENT_ALTERNATE_FONT_PATH_2 \
+"/usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Speedo/,\
+/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,\
+/usr/share/fonts/X11/100dpi/,/usr/share/fonts/X11/TTF/"
+
+#define NXAGENT_ALTERNATE_FONT_PATH_3 \
+"/usr/X11R6/lib/X11/fonts/misc/,/usr/X11R6/lib/X11/fonts/Speedo/,\
+/usr/X11R6/lib/X11/fonts/Type1/,/usr/X11R6/lib/X11/fonts/75dpi/,\
+/usr/X11R6/lib/X11/fonts/100dpi/,/usr/X11R6/lib/X11/fonts/TTF/"
+
+#undef NXAGENT_FONTCACHE_DEBUG
+#undef NXAGENT_RECONNECT_FONT_DEBUG
+#undef NXAGENT_FONTMATCH_DEBUG
+
+#define FIELDS 14
+
+static int reconnectFlexibility;
+
+static void nxagentCleanCacheAfterReconnect(void);
+static void nxagentFontReconnect(FontPtr, XID, void *);
+static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont);
+static XFontStruct *nxagentLoadQueryFont(register Display *dpy , char *fontName , FontPtr pFont);
+int nxagentFreeFont(XFontStruct *fs);
+static Bool nxagentGetFontServerPath(char * fontServerPath);
+
+static char * nxagentMakeScalableFontName(const char *fontName, int scalableResolution);
+
+RESTYPE RT_NX_FONT;
+
+#ifdef NXAGENT_RECONNECT_FONT_DEBUG
+static void printFontCacheDump(char*);
+#endif
+
+typedef struct _nxagentFontRec
+{
+ char *name;
+ int status;
+} nxagentFontRec, *nxagentFontRecPtr;
+
+typedef struct _nxagentFontList
+{
+ nxagentFontRecPtr *list;
+ int length;
+ int listSize;
+} nxagentFontList, *nxagentFontListPtr;
+
+nxagentFontList nxagentRemoteFontList = {NULL, (int)0, (int)0};
+
+int nxagentFontPrivateIndex;
+
+typedef struct _nxCacheFontEntry
+{
+ Atom atom;
+ XFontStruct *font_struct;
+ char *name;
+} nxCacheFontEntryRec, *nxCacheFontEntryRecPtr;
+
+static struct _nxagentFontCache
+{
+ nxCacheFontEntryRecPtr *entry;
+ int index;
+ int size;
+} nxagentFontCache = { NULL, (int) 0, (int) 0 };
+
+#define CACHE_ENTRY_PTR (nxagentFontCache.entry)
+#define CACHE_INDEX (nxagentFontCache.index)
+#define CACHE_SIZE (nxagentFontCache.size)
+#define CACHE_ENTRY(A) (CACHE_ENTRY_PTR[A])
+#define CACHE_FSTRUCT(A) (CACHE_ENTRY(A) -> font_struct)
+#define CACHE_NAME(A) (CACHE_ENTRY(A) -> name)
+#define CACHE_ATOM(A) (CACHE_ENTRY(A) -> atom)
+
+static struct _nxagentFailedToReconnectFonts
+{
+ FontPtr *font;
+ XID *id;
+ int size;
+ int index;
+} nxagentFailedToReconnectFonts = {NULL, NULL, 0, 0};
+
+/*
+ * This is used if nxagentFullGeneration is true
+ * in CloseDisplay().
+ */
+
+void nxagentFreeFontCache(void)
+{
+ int i;
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: Freeing nxagent font cache\n");
+ #endif
+
+ if (CACHE_INDEX == 0)
+ return;
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: Freeing nxagent font cache, there are [%d] entries.\n", CACHE_INDEX);
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: Freeing nxagent font cache entry [%d] entry pointer is [%p], name [%s]\n",
+ i, CACHE_ENTRY(i), CACHE_NAME(i));
+ #endif
+
+ if (CACHE_FSTRUCT(i))
+ {
+ nxagentFreeFont(CACHE_FSTRUCT(i));
+ }
+
+ free(CACHE_NAME(i));
+ free(CACHE_ENTRY(i));
+ }
+
+ free(CACHE_ENTRY_PTR);
+ CACHE_ENTRY_PTR = NULL;
+ CACHE_INDEX = 0;
+ CACHE_SIZE = 0;
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: nxagent font cache fully freed\n");
+ #endif
+
+ return;
+}
+
+void nxagentListRemoteFonts(const char *searchPattern, const int maxNames)
+{
+ int i, q, p;
+
+ char **xList;
+ int xLen = 0;
+
+ const char *patterns[] = {"*", "-*-*-*-*-*-*-*-*-*-*-*-*-*-*"};
+ int patternsQt = 2;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return;
+ }
+
+ /*
+ * Avoid querying again the remote
+ * fonts.
+ */
+
+ if (nxagentRemoteFontList.length > 0)
+ {
+ return;
+ }
+
+ /*
+ * We can't retrieve the full remote font
+ * list with a single query, because the
+ * number of dashes in the pattern acts as
+ * a rule to select how to search for the
+ * font names, so the pattern '*' is useful
+ * to retrive the font aliases, while the
+ * other one will select the 'real' fonts.
+ */
+
+ for (p = 0; p < patternsQt; p++)
+ {
+ xList = XListFonts(nxagentDisplay, patterns[p], maxNames, &xLen);
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "nxagentListRemoteFonts: NXagent remote list [%s] has %d elements.\n", patterns[p], xLen);
+ #endif
+
+ /*
+ * Add the ListFont request pattern to the list with
+ * the last requested maxnames.
+ */
+
+ nxagentListRemoteAddName(searchPattern, maxNames);
+
+ for (i = 0; i < xLen; i++)
+ {
+ q = 1;
+
+ nxagentListRemoteAddName(xList[i], q);
+ }
+
+ XFreeFontNames(xList);
+ }
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+
+ fprintf(stderr, "nxagentListRemoteFonts: Printing remote font list.\n");
+
+ for (i = 0; i < nxagentRemoteFontList.length; i++)
+ {
+ fprintf(stderr, "Font# %d, \"%s\"\n", i, nxagentRemoteFontList.list[i]->name);
+ }
+
+ fprintf(stderr, "nxagentListRemoteFonts: End of list\n");
+
+ #endif
+}
+
+void nxagentListRemoteAddName(const char *name, int status)
+{
+ int pos;
+
+ if (nxagentFontFind(name, &pos))
+ {
+ if (nxagentRemoteFontList.list[pos]->status < status)
+ {
+ nxagentRemoteFontList.list[pos]->status = status;
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "Font: Font# %d, [%s] change status to %s\n",
+ pos, nxagentRemoteFontList.list[pos]->name,nxagentRemoteFontList.list[pos]->status?"OK":"deleted");
+ #endif
+ }
+ return;
+ }
+
+ if (nxagentRemoteFontList.length == nxagentRemoteFontList.listSize)
+ {
+ nxagentRemoteFontList.list = realloc(nxagentRemoteFontList.list, sizeof(nxagentFontRecPtr)
+ * (nxagentRemoteFontList.listSize + 1000));
+
+ if (nxagentRemoteFontList.list == NULL)
+ {
+ FatalError("Font: remote list memory re-allocation failed!.\n");
+ }
+
+ nxagentRemoteFontList.listSize += 1000;
+ }
+
+ if (pos < nxagentRemoteFontList.length)
+ {
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "Font: Going to move list from %p to %p len = %d!.\n",
+ &nxagentRemoteFontList.list[pos], &nxagentRemoteFontList.list[pos+1],
+ (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr));
+ #endif
+
+ memmove(&nxagentRemoteFontList.list[pos+1],
+ &nxagentRemoteFontList.list[pos],
+ (nxagentRemoteFontList.length - pos) * sizeof(nxagentFontRecPtr));
+ }
+
+ if ((nxagentRemoteFontList.list[pos] = malloc(sizeof(nxagentFontRec))))
+ {
+ nxagentRemoteFontList.list[pos]->name = malloc(strlen(name) +1);
+ if (nxagentRemoteFontList.list[pos]->name == NULL)
+ {
+ fprintf(stderr, "Font: remote list name memory allocation failed!.\n");
+ return;
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Font: remote list record memory allocation failed!.\n");
+ return;
+ }
+ strcpy(nxagentRemoteFontList.list[pos]->name,name);
+ nxagentRemoteFontList.list[pos]->status = status;
+ nxagentRemoteFontList.length++;
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "Font: remote font list added [%s] in position [%d] as %s !.\n",
+ name, pos, status ? "OK" : "deleted");
+ fprintf(stderr, "Font: remote font list total len is [%d] Size is [%d] !.\n",
+ nxagentRemoteFontList.length, nxagentRemoteFontList.listSize);
+ #endif
+}
+
+static void nxagentFreeRemoteFontList(nxagentFontList *listRec)
+{
+ int l;
+
+ for (l = 0; l < listRec -> length; l++)
+ {
+ if (listRec -> list[l])
+ {
+ free(listRec -> list[l] -> name);
+ listRec -> list[l] -> name = NULL;
+
+ free(listRec -> list[l]);
+ listRec -> list[l] = NULL;
+ }
+ }
+
+ listRec -> length = listRec -> listSize = 0;
+
+ free(listRec -> list);
+ listRec -> list = NULL;
+
+ return;
+}
+
+Bool nxagentFontFind(const char *name, int *pos)
+{
+ int low,high,res,iter,lpos;
+
+ if (!nxagentRemoteFontList.length)
+ {
+ *pos=0;
+ return False;
+ }
+ low = 0;
+ high = nxagentRemoteFontList.length - 1;
+ iter = 0;
+ res = 1;
+ lpos = nxagentRemoteFontList.length;
+ while (low <= high)
+ {
+ *pos = (high + low)/2;
+ iter ++;
+ res = strcasecmp(nxagentRemoteFontList.list[*pos]->name,name);
+ if (res > 0)
+ {
+ high = *pos - 1;
+ lpos = *pos;
+ continue;
+ }
+ else if (res < 0)
+ {
+ low = *pos + 1;
+ lpos = low;
+ continue;
+ }
+ break;
+ }
+ *pos = (res == 0)?*pos:lpos;
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ if (res == 0)
+ fprintf(stderr, "Font: font found in %d iterations in pos = %d\n", iter, *pos);
+ else
+ fprintf(stderr, "Font: not font found in %d iterations insertion pos is = %d\n", iter, *pos);
+ #endif
+
+ return (res == 0);
+
+}
+
+Bool nxagentFontLookUp(const char *name)
+{
+ int i;
+ int result;
+
+ char *scalable;
+
+ if (name != NULL && strlen(name) == 0)
+ {
+ return 0;
+ }
+
+ result = nxagentFontFind(name, &i);
+
+ scalable = NULL;
+
+ /*
+ * Let's try with the scalable font description.
+ */
+
+ if (result == 0)
+ {
+ scalable = nxagentMakeScalableFontName(name, 0);
+
+ if (scalable != NULL)
+ {
+ result = nxagentFontFind(scalable, &i);
+
+ free(scalable);
+ }
+ }
+
+ /*
+ * Let's try again after replacing zero to xdpi and ydpi in the pattern.
+ */
+
+ if (result == 0)
+ {
+ scalable = nxagentMakeScalableFontName(name, 1);
+
+ if (scalable != NULL)
+ {
+ result = nxagentFontFind(scalable, &i);
+
+ free(scalable);
+ }
+ }
+
+ if (result == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (nxagentRemoteFontList.list[i]->status > 0);
+ }
+}
+
+Bool nxagentRealizeFont(ScreenPtr pScreen, FontPtr pFont)
+{
+ void * priv;
+ Atom name_atom, value_atom;
+ int nprops;
+ FontPropPtr props;
+ int i;
+ const char *name;
+ char *origName = (char*) pScreen;
+
+#ifdef HAS_XFONT2
+ xfont2_font_set_private(pFont, nxagentFontPrivateIndex, NULL);
+#else
+ FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL);
+#endif /* HAS_XFONT2 */
+
+ if (requestingClient && XpClientIsPrintClient(requestingClient, NULL))
+ return True;
+
+ name_atom = MakeAtom("FONT", 4, True);
+ value_atom = 0L;
+
+ nprops = pFont->info.nprops;
+ props = pFont->info.props;
+
+ for (i = 0; i < nprops; i++)
+ if ((Atom)props[i].name == name_atom) {
+ value_atom = props[i].value;
+ break;
+ }
+
+ if (!value_atom) return False;
+
+ name = NameForAtom(value_atom);
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: nxagentRealizeFont, realizing font: %s\n", validateString(name));
+ fprintf(stderr, " atom: %ld\n", value_atom);
+ fprintf(stderr, "Font: Cache dump:\n");
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ fprintf(stderr, "nxagentFontCache.entry[%d]->name: %s font_struct at %p\n",
+ i, CACHE_NAME(i), CACHE_FSTRUCT(i));
+ }
+ #endif
+
+ if (!name) return False;
+
+ if ((strcasecmp(origName, name) != 0) && !strchr(origName,'*'))
+ {
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "Font: Changing font name to realize from [%s] to [%s]\n",
+ validateString(name), origName);
+ #endif
+
+ name = origName;
+ }
+
+ priv = (void *)malloc(sizeof(nxagentPrivFont));
+#ifdef HAS_XFONT2
+ xfont2_font_set_private(pFont, nxagentFontPrivateIndex, priv);
+#else
+ FontSetPrivate(pFont, nxagentFontPrivateIndex, priv);
+#endif /* HAS_XFONT2 */
+
+ nxagentFontPriv(pFont) -> mirrorID = 0;
+
+ for (i = 0; i < nxagentFontCache.index; i++)
+ {
+/* if (value_atom == CACHE_ATOM(i))*/
+ if (strcasecmp(CACHE_NAME(i), name) == 0)
+ {
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: nxagentFontCache hit [%s] = [%s]!\n", CACHE_NAME(i), validateString(name));
+ #endif
+
+ break;
+ }
+ }
+
+ if (i < CACHE_INDEX)
+ {
+ nxagentFontPriv(pFont)->font_struct = CACHE_FSTRUCT(i);
+ strcpy(nxagentFontPriv(pFont)->fontName, name);
+ }
+ else
+ {
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: nxagentFontCache fail.\n");
+ #endif
+
+ if (CACHE_INDEX == CACHE_SIZE)
+ {
+ CACHE_ENTRY_PTR = realloc(CACHE_ENTRY_PTR, sizeof(nxCacheFontEntryRecPtr) * (CACHE_SIZE + 100));
+
+ if (CACHE_ENTRY_PTR == NULL)
+ {
+ FatalError("Font: Cache list memory re-allocation failed.\n");
+ }
+
+ CACHE_SIZE += 100;
+ }
+
+ CACHE_ENTRY(CACHE_INDEX) = malloc(sizeof(nxCacheFontEntryRec));
+
+ if (CACHE_ENTRY(CACHE_INDEX) == NULL)
+ {
+ return False;
+ }
+
+ CACHE_NAME(CACHE_INDEX) = malloc(strlen(name) + 1);
+
+ if (CACHE_NAME(CACHE_INDEX) == NULL)
+ {
+ return False;
+ }
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+ fprintf(stderr, "Font: Going to realize font [%s],[%s] on real X server.\n", validateString(name), origName);
+ #endif
+
+ if (nxagentRemoteFontList.length == 0 && (NXDisplayError(nxagentDisplay) == 0))
+ {
+ nxagentListRemoteFonts("*", nxagentMaxFontNames);
+ }
+
+ nxagentFontPriv(pFont)->font_struct = nxagentLoadQueryFont(nxagentDisplay, (char *)name, pFont);
+ strcpy(nxagentFontPriv(pFont)->fontName, name);
+ if (nxagentFontPriv(pFont)->font_struct != NULL)
+ {
+ CACHE_ATOM(i) = value_atom;
+ strcpy(CACHE_NAME(i), name);
+ CACHE_FSTRUCT(i) = nxagentFontPriv(pFont)->font_struct;
+ CACHE_INDEX++;
+
+ nxagentFontPriv(pFont) -> mirrorID = FakeClientID(serverClient -> index);
+ AddResource(nxagentFontPriv(pFont) -> mirrorID, RT_NX_FONT, pFont);
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "Font: nxagentFontCache adds font [%s] in pos. [%d].\n",
+ validateString(name), CACHE_INDEX - 1);
+ #endif
+ }
+ }
+
+ #ifdef NXAGENT_FONTMATCH_DEBUG
+
+ if (nxagentFontPriv(pFont)->font_struct == NULL)
+ {
+ if (nxagentFontLookUp(name) == False)
+ {
+ fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s, not in our remote list\n",
+ validateString(name));
+ }
+ else
+ {
+ fprintf(stderr, "Font: nxagentRealizeFont failed with font Font=%s but the font is in our remote list\n",
+ validateString(name));
+ }
+ }
+ else
+ fprintf(stderr, "Font: nxagentRealizeFont OK realizing font Font=%s\n",
+ validateString(name));
+
+ #endif
+
+ return (nxagentFontPriv(pFont)->font_struct != NULL);
+}
+
+Bool nxagentUnrealizeFont(ScreenPtr pScreen, FontPtr pFont)
+{
+ if (nxagentFontPriv(pFont))
+ {
+ if (NXDisplayError(nxagentDisplay) == 0)
+ {
+ if (nxagentFontStruct(pFont))
+ {
+ int i;
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (CACHE_FSTRUCT(i) == nxagentFontStruct(pFont))
+ {
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "nxagentUnrealizeFont: Not freeing the font in cache.\n");
+ #endif
+
+ break;
+ }
+ }
+
+ if (i == CACHE_INDEX)
+ {
+ /*
+ * This font is not in the cache.
+ */
+
+ #ifdef NXAGENT_FONTCACHE_DEBUG
+ fprintf(stderr, "nxagentUnrealizeFont: Freeing font not found in cache '%d'\n",
+ CACHE_ATOM(i));
+ #endif
+
+ XFreeFont(nxagentDisplay, nxagentFontStruct(pFont));
+ }
+ }
+ }
+
+ if (nxagentFontPriv(pFont) -> mirrorID)
+ FreeResource(nxagentFontPriv(pFont) -> mirrorID, RT_NONE);
+
+ free(nxagentFontPriv(pFont));
+#ifdef HAS_XFONT2
+ xfont2_font_set_private(pFont, nxagentFontPrivateIndex, NULL);
+#else
+ FontSetPrivate(pFont, nxagentFontPrivateIndex, NULL);
+#endif /* HAS_XFONT2 */
+ }
+
+ return True;
+}
+
+int nxagentDestroyNewFontResourceType(void * p, XID id)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyNewFontResourceType: Destroying mirror id [%ld] for font at [%p].\n",
+ nxagentFontPriv((FontPtr) p) -> mirrorID, (void *) p);
+ #endif
+
+/*
+FIXME: It happens that this resource had been already
+ destroied. We should verify if the same font is
+ assigned both to the server client and another
+ client. We had a crash when freeing server client
+ resources.
+*/
+ if (nxagentFontPriv((FontPtr) p) != NULL)
+ {
+ nxagentFontPriv((FontPtr) p) -> mirrorID = None;
+ }
+
+ return 1;
+}
+
+static XFontStruct *nxagentLoadBestQueryFont(Display* dpy, char *fontName, FontPtr pFont)
+{
+ XFontStruct *fontStruct;
+
+ char *substFontBuf;
+
+ /* X Logical Font Description Conventions
+ * require 14 fields in the font names.
+ *
+ */
+ char *searchFields[FIELDS+1];
+ char *fontNameFields[FIELDS+1];
+ int i;
+ int j;
+ int numSearchFields = 0;
+ int numFontFields = 0;
+ int weight = 0;
+ int tempWeight = 1;
+ int fieldOrder[14] = { 4, /* Slant */
+ 11, /* Spacing */
+ 12, /* Width info */
+ 13, /* Charset */
+ 14, /* Language */
+ 7, /* Height */
+ 6, /* Add-style */
+ 3, /* Weight */
+ 2, /* Name */
+ 1, /* Foundry */
+ 9, /* DPI_x */
+ 5, /* Set-width */
+ 8, /* Point size */
+ 10 /* DPI_y */
+ };
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentLoadBestQueryFont: Searching font '%s' .\n", fontName);
+ #endif
+
+ substFontBuf = (char *) malloc(sizeof(char) * 512);
+
+
+ numFontFields = nxagentSplitString(fontName, fontNameFields, FIELDS + 1, "-");
+
+ memcpy(substFontBuf, "fixed\0", strlen("fixed") + 1);
+
+ if (numFontFields <= FIELDS)
+ {
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Font name in non standard format. \n");
+ }
+ #endif
+ }
+ else
+ {
+ for (i = 1 ; i < nxagentRemoteFontList.length ; i++)
+ {
+ numSearchFields = nxagentSplitString(nxagentRemoteFontList.list[i]->name, searchFields, FIELDS+1, "-");
+
+
+ /* The following code attemps to find an accurate approximation
+ * of the missing font. The current candidate and the missing font are
+ * compared on the 14 fields of the X Logical Font Description Convention.
+ * The selection is performed by the analysis of the matching fields,
+ * shifting left the value of the Weight variable on the right matches
+ * and shifting right the value of the Weight on the wrong ones;
+ * due a probability of overmuch right shifting, the starting weight is set
+ * to a high value. At the end of matching the selected font is the one
+ * with the bigger final Weight. The shift operation has been used instead
+ * of other operation for a performance issue.
+ * In some check the shift is performed by more than one position, because
+ * of the relevance of the field; for example a correct slant or a matching
+ * charset is more relevant than the size.
+ */
+
+ if (numSearchFields > FIELDS)
+ {
+
+ tempWeight = 0;
+
+ for (j = 0; j < FIELDS; j++)
+ {
+ if (strcasecmp(searchFields[fieldOrder[j]], fontNameFields[fieldOrder[j]]) == 0 ||
+ strcmp(searchFields[fieldOrder[j]], "") == 0 ||
+ strcmp(fontNameFields[fieldOrder[j]], "") != 0 ||
+ strcmp(searchFields[fieldOrder[j]], "*") == 0 ||
+ strcmp(fontNameFields[fieldOrder[j]], "*") == 0)
+ {
+ tempWeight ++;
+ }
+
+ tempWeight <<= 1;
+ }
+
+ }
+
+ if (tempWeight > weight)
+ {
+ /* Found more accurate font */
+
+ weight = tempWeight;
+ memcpy(substFontBuf, nxagentRemoteFontList.list[i]->name, strlen(nxagentRemoteFontList.list[i]->name));
+ substFontBuf[strlen(nxagentRemoteFontList.list[i]->name)] = '\0';
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentLoadBestQueryFont: Weight '%d' of more accurate font '%s' .\n", weight, substFontBuf);
+ #endif
+ }
+
+ for (j = 0; j < numSearchFields; j++)
+ {
+ if (searchFields[j] != NULL)
+ {
+ free(searchFields[j]);
+ }
+ }
+ }
+ }
+
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentLoadBestQueryFont: WARNING! Failed to load font '%s'. Replacing with '%s'.\n",
+ fontName, substFontBuf);
+ }
+ #endif
+
+ fontStruct = nxagentLoadQueryFont(dpy, substFontBuf, pFont);
+
+ free (substFontBuf);
+
+ for (j = 0; j < numFontFields; j++)
+ {
+ if (fontNameFields[j] != NULL)
+ {
+ free(fontNameFields[j]);
+ }
+ }
+
+ return fontStruct;
+}
+
+static void nxagentFontDisconnect(FontPtr pFont, XID param1, void * param2)
+{
+ nxagentPrivFont *privFont;
+ Bool *pBool = (Bool*)param2;
+ int i;
+
+ if (pFont == NULL || !*pBool)
+ return;
+
+ privFont = nxagentFontPriv(pFont);
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontDisconnect: pFont %p, XID %lx\n",
+ (void *) pFont, privFont -> font_struct ? nxagentFont(pFont) : 0);
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontDisconnect: font %s found in cache at position %d\n",
+ privFont -> fontName, i);
+ #endif
+
+ privFont -> font_struct = NULL;
+ return;
+ }
+ }
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontDisconnect: WARNING font %s not found in cache freeing it now\n",
+ privFont -> fontName);
+ #endif
+
+ if (privFont -> font_struct)
+ {
+ XFreeFont(nxagentDisplay, privFont -> font_struct);
+ privFont -> font_struct = NULL;
+ }
+}
+
+static void nxagentCollectFailedFont(FontPtr fpt, XID id)
+{
+
+ if (nxagentFailedToReconnectFonts.font == NULL)
+ {
+ nxagentFailedToReconnectFonts.size = 8;
+
+ nxagentFailedToReconnectFonts.font = malloc(nxagentFailedToReconnectFonts.size *
+ sizeof(FontPtr));
+
+ nxagentFailedToReconnectFonts.id = malloc(nxagentFailedToReconnectFonts.size * sizeof(XID));
+
+ if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL)
+ {
+ FatalError("Font: font not reconnected memory allocation failed!.\n");
+ }
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentCollectFailedFont: allocated [%d] bytes.\n",
+ 8 * (sizeof(FontPtr)+ sizeof(XID)));
+ #endif
+ }
+ else if (nxagentFailedToReconnectFonts.index == nxagentFailedToReconnectFonts.size - 1)
+ {
+ nxagentFailedToReconnectFonts.size *= 2;
+
+ nxagentFailedToReconnectFonts.font = realloc(nxagentFailedToReconnectFonts.font,
+ nxagentFailedToReconnectFonts.size *
+ sizeof(FontPtr));
+
+ nxagentFailedToReconnectFonts.id = realloc(nxagentFailedToReconnectFonts.id,
+ nxagentFailedToReconnectFonts.size *
+ sizeof(XID));
+
+ if (nxagentFailedToReconnectFonts.font == NULL || nxagentFailedToReconnectFonts.id == NULL)
+ {
+ FatalError("Font: font not reconnected memory re-allocation failed!.\n");
+ }
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr,"nxagentCollectFailedFont: reallocated memory.\n ");
+ #endif
+ }
+
+ nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index] = fpt;
+
+ nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index] = id;
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentCollectFailedFont: font not reconnected at [%p], "
+ "put in nxagentFailedToReconnectFonts.font[%d] = [%p], with XID = [%lu].\n",
+ (void*) fpt, nxagentFailedToReconnectFonts.index,
+ (void *)nxagentFailedToReconnectFonts.font[nxagentFailedToReconnectFonts.index],
+ nxagentFailedToReconnectFonts.id[nxagentFailedToReconnectFonts.index]);
+ #endif
+
+ nxagentFailedToReconnectFonts.index++;
+}
+
+static void nxagentFontReconnect(FontPtr pFont, XID param1, void * param2)
+{
+ int i;
+ nxagentPrivFont *privFont;
+ Bool *pBool = (Bool*)param2;
+
+ if (pFont == NULL)
+ return;
+
+ privFont = nxagentFontPriv(pFont);
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontReconnect: pFont %p - XID %lx - name %s\n",
+ (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0,
+ privFont -> fontName);
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "\tfound in cache");
+ #endif
+
+ if (!CACHE_FSTRUCT(i))
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, " --- font struct not valid\n");
+ #endif
+
+ break;
+ }
+
+ nxagentFontStruct(pFont) = CACHE_FSTRUCT(i);
+
+ return;
+ }
+ }
+
+ if (i == CACHE_INDEX)
+ {
+ FatalError("nxagentFontReconnect: font not found in cache.");
+ }
+
+ privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont);
+
+ if ((privFont -> font_struct == NULL) && reconnectFlexibility)
+ {
+ privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont);
+ }
+
+ if (privFont->font_struct != NULL)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid);
+ #endif
+
+ CACHE_FSTRUCT(i) = privFont -> font_struct;
+ }
+ else
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontReconnect: failed\n");
+ #endif
+
+ nxagentCollectFailedFont(pFont, param1);
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFontReconnect: reconnection of font [%s] failed.\n",
+ privFont -> fontName);
+ #endif
+
+ nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT,
+ "Couldn't restore the font '%s'", privFont -> fontName);
+
+ *pBool = False;
+ }
+
+ return;
+}
+
+static void nxagentFreeCacheBeforeReconnect(void)
+{
+ int i;
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ printFontCacheDump("nxagentFreeCacheBeforeReconnect");
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (CACHE_FSTRUCT(i))
+ {
+ nxagentFreeFont(CACHE_FSTRUCT(i));
+ CACHE_FSTRUCT(i) = NULL;
+ }
+ }
+}
+
+static void nxagentCleanCacheAfterReconnect(void)
+{
+ int i, j;
+ int real_size = CACHE_INDEX;
+ nxCacheFontEntryRecPtr swapEntryPtr;
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ printFontCacheDump("nxagentCleanCacheAfterReconnect");
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if(CACHE_FSTRUCT(i) == NULL)
+ {
+ XFree(CACHE_NAME(i));
+ real_size--;
+ }
+ }
+
+ for (i = 0; i < real_size; i++)
+ {
+ /* Find - first bad occurrence if exist. */
+ while ((i < real_size) && CACHE_FSTRUCT(i)) i++;
+
+ /* Really nothing more to do. */
+ if (i == real_size)
+ break;
+
+ /*
+ * Find - first good occurrence (moving backward from right end) entry in
+ * order to replace the bad one.
+ */
+ for (j = CACHE_INDEX - 1; CACHE_FSTRUCT(j) == NULL; j--);
+
+ /*
+ * Now we can swap the two entry
+ * and reduce the Cache index
+ */
+ swapEntryPtr = CACHE_ENTRY(i);
+ CACHE_ENTRY(i) = CACHE_ENTRY(j);
+ CACHE_ENTRY(j) = swapEntryPtr;
+ }
+
+ CACHE_INDEX = real_size;
+}
+
+#ifdef NXAGENT_RECONNECT_FONT_DEBUG
+static void printFontCacheDump(char* msg)
+{
+ int i;
+
+ fprintf(stderr, "%s - begin -\n", msg);
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (CACHE_FSTRUCT(i))
+ {
+ fprintf(stderr, "\tXID %lx - %s\n", CACHE_FSTRUCT(i) -> fid, CACHE_NAME(i));
+ }
+ else
+ {
+ fprintf(stderr, "\tdestroyed - %s\n", CACHE_NAME(i));
+ }
+ }
+ fprintf(stderr, "%s - end -\n", msg);
+}
+#endif
+
+Bool nxagentReconnectAllFonts(void *p0)
+{
+ int cid;
+ Bool fontSuccess = True;
+
+ reconnectFlexibility = *((int *) p0);
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG)
+ fprintf(stderr, "nxagentReconnectAllFonts\n");
+ #endif
+
+ /*
+ * The resource type RT_NX_FONT is created on the
+ * server client only, so we can avoid to loop
+ * through all the clients.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT,
+ (FindResType) nxagentFontReconnect, &fontSuccess);
+
+ for (cid = 0; cid < MAXCLIENTS; cid++)
+ {
+ if (clients[cid])
+ {
+ FindClientResourcesByType(clients[cid], RT_FONT,
+ (FindResType) nxagentFontReconnect, &fontSuccess);
+ }
+ }
+
+ if (fontSuccess)
+ {
+ nxagentCleanCacheAfterReconnect();
+ }
+
+ return fontSuccess;
+}
+
+static void nxagentFailedFontReconnect(FontPtr pFont, XID param1, void * param2)
+{
+ int i;
+ nxagentPrivFont *privFont;
+ Bool *pBool = (Bool*)param2;
+
+ if (pFont == NULL)
+ return;
+
+ privFont = nxagentFontPriv(pFont);
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFailedFontReconnect: pFont %p - XID %lx - name %s\n",
+ (void*) pFont, (privFont -> font_struct) ? nxagentFont(pFont) : 0,
+ privFont -> fontName);
+ #endif
+
+ for (i = 0; i < CACHE_INDEX; i++)
+ {
+ if (strcasecmp(CACHE_NAME(i), privFont -> fontName) == 0)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "\tfound in cache");
+ #endif
+
+ if (!CACHE_FSTRUCT(i))
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, " --- font struct not valid\n");
+ #endif
+
+ break;
+ }
+
+ nxagentFontStruct(pFont) = CACHE_FSTRUCT(i);
+
+ return;
+ }
+ }
+
+ if (i == CACHE_INDEX)
+ {
+ FatalError("nxagentFailedFontReconnect: font not found in cache.");
+ }
+
+ privFont -> font_struct = nxagentLoadQueryFont(nxagentDisplay, privFont -> fontName, pFont);
+
+ if (privFont -> font_struct == NULL)
+ {
+ privFont -> font_struct = nxagentLoadBestQueryFont(nxagentDisplay, privFont -> fontName, pFont);
+ }
+
+ if (privFont->font_struct != NULL)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "\tXID %lx\n", privFont -> font_struct -> fid);
+ #endif
+
+ CACHE_FSTRUCT(i) = privFont -> font_struct;
+ }
+ else
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFailedFontReconnect: failed\n");
+ #endif
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentFailedFontReconnect: reconnection of font [%s] failed.\n",
+ privFont -> fontName);
+ #endif
+
+ nxagentSetReconnectError(FAILED_RESUME_FONTS_ALERT,
+ "Couldn't restore the font '%s'", privFont -> fontName);
+
+ *pBool = False;
+ }
+
+ return;
+}
+
+static void nxagentFreeFailedToReconnectFonts()
+{
+ if (nxagentFailedToReconnectFonts.font != NULL)
+ {
+ free(nxagentFailedToReconnectFonts.font);
+ nxagentFailedToReconnectFonts.font = NULL;
+ }
+
+ if (nxagentFailedToReconnectFonts.id != NULL)
+ {
+ free(nxagentFailedToReconnectFonts.id);
+ nxagentFailedToReconnectFonts.id = NULL;
+ }
+
+ nxagentFailedToReconnectFonts.size = 0;
+ nxagentFailedToReconnectFonts.index = 0;
+}
+
+Bool nxagentReconnectFailedFonts(void *p0)
+{
+ int i;
+ int attempt = 1;
+ const int maxAttempt = 5;
+
+ char **fontPaths, **localFontPaths, **newFontPaths;
+ char fontServerPath[256] = "";
+ int nPaths = 0;
+
+ Bool repeat = True;
+ Bool fontSuccess = True;
+
+ reconnectFlexibility = *((int *) p0);
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentReconnectFailedFonts: \n");
+ #endif
+
+ if (nxagentGetFontServerPath(fontServerPath) == False)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectFailedFonts: WARNING! "
+ "Font server tunneling not retrieved.\n");
+ #endif
+ }
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentReconnectFailedFonts: font server path [%s]\n", fontServerPath);
+ #endif
+
+ fontPaths = XGetFontPath(nxagentDisplay, &nPaths);
+
+ if ((newFontPaths = malloc((nPaths + 1) * sizeof(char *))) == NULL)
+ {
+ FatalError("nxagentReconnectFailedFonts: malloc failed.");
+ }
+
+ memcpy(newFontPaths, fontPaths, nPaths * sizeof(char*));
+
+ localFontPaths = newFontPaths;
+ localFontPaths += nPaths;
+ *localFontPaths = fontServerPath;
+
+ while(repeat)
+ {
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentReconnectFailedFonts: attempt [%d].\n", attempt);
+ #endif
+
+ repeat = False;
+
+ XSetFontPath(nxagentDisplay, newFontPaths, nPaths + 1);
+ nxagentFreeRemoteFontList(&nxagentRemoteFontList);
+ nxagentListRemoteFonts("*", nxagentMaxFontNames);
+
+ for(i = 0; i < nxagentFailedToReconnectFonts.index; i++)
+ {
+ fontSuccess = True;
+
+ if(nxagentFailedToReconnectFonts.font[i])
+ {
+ nxagentFailedFontReconnect(nxagentFailedToReconnectFonts.font[i],
+ nxagentFailedToReconnectFonts.id[i],
+ &fontSuccess);
+
+ if (fontSuccess)
+ {
+ nxagentFailedToReconnectFonts.font[i] = NULL;
+ }
+ else
+ {
+ repeat = True;
+ }
+
+ }
+ }
+
+ attempt++;
+
+ if (attempt > maxAttempt)
+ {
+ nxagentFreeFailedToReconnectFonts();
+
+ XSetFontPath(nxagentDisplay, fontPaths, nPaths);
+ nxagentFreeRemoteFontList(&nxagentRemoteFontList);
+ nxagentListRemoteFonts("*", nxagentMaxFontNames);
+
+ XFreeFontPath(fontPaths);
+ free(newFontPaths);
+
+ return False;
+ }
+ }
+
+ nxagentFreeFailedToReconnectFonts();
+
+ XSetFontPath(nxagentDisplay, fontPaths, nPaths);
+
+ XFreeFontPath(fontPaths);
+ free(newFontPaths);
+
+ nxagentCleanCacheAfterReconnect();
+
+ return True;
+}
+
+Bool nxagentDisconnectAllFonts()
+{
+ int cid;
+ Bool fontSuccess = True;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_FONT_DEBUG)
+ fprintf(stderr, "nxagentDisconnectAllFonts\n");
+ #endif
+
+ nxagentFreeRemoteFontList(&nxagentRemoteFontList);
+ nxagentFreeCacheBeforeReconnect();
+
+ /*
+ * The resource type RT_NX_FONT is created on the
+ * server client only, so we can avoid to loop
+ * through all the clients.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_FONT,
+ (FindResType) nxagentFontDisconnect, &fontSuccess);
+
+ for(cid = 0; cid < MAXCLIENTS; cid++)
+ {
+ if( clients[cid] && fontSuccess )
+ {
+ FindClientResourcesByType(clients[cid], RT_FONT,
+ (FindResType) nxagentFontDisconnect, &fontSuccess);
+ }
+ }
+
+ return True;
+}
+
+static Bool nxagentGetFontServerPath(char * fontServerPath)
+{
+ char path[256];
+
+ if (NXGetFontParameters(nxagentDisplay, 256, path) == True)
+ {
+ if (*path != '\0')
+ {
+ strncpy(fontServerPath, path + 1, *path);
+
+ *(fontServerPath + *path) = '\0';
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetFontServerPath: Got path [%s].\n",
+ fontServerPath);
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetFontServerPath: WARNING! Font server tunneling not enabled.\n");
+ #endif
+
+ return False;
+ }
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetFontServerPath: WARNING! Failed to get path for font server tunneling.\n");
+ #endif
+
+ return False;
+ }
+
+ return True;
+}
+
+void nxagentVerifyDefaultFontPath(void)
+{
+ struct stat dirStat;
+ static char *fontPath;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Going to search for one or more valid font paths.\n");
+ #endif
+
+ fontPath = malloc(strlen(defaultFontPath) + 1);
+
+ if (fontPath == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Unable to allocate memory for a new font path. "
+ "Using the default font path [%s].\n", validateString(defaultFontPath));
+ #endif
+
+ return;
+ }
+
+ /*
+ * Set the default font path as the first choice.
+ */
+
+ strcpy(fontPath, defaultFontPath);
+
+ if (stat(NXAGENT_DEFAULT_FONT_DIR, &dirStat) == 0 &&
+ S_ISDIR(dirStat.st_mode) != 0)
+ {
+ /*
+ * Let's use the old "/usr/share/nx/fonts" style.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n",
+ validateString(NXAGENT_DEFAULT_FONT_DIR));
+ #endif
+
+ if (*fontPath != '\0')
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 2);
+ strcat(fontPath, ",");
+ }
+ else
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_DEFAULT_FONT_PATH) + 1);
+ }
+
+ strcat(fontPath, NXAGENT_DEFAULT_FONT_PATH);
+ }
+
+ if (stat(NXAGENT_ALTERNATE_FONT_DIR, &dirStat) == 0 &&
+ S_ISDIR(dirStat.st_mode) != 0)
+ {
+ /*
+ * Let's use the new "/usr/share/X11/fonts" path.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n",
+ validateString(NXAGENT_ALTERNATE_FONT_DIR));
+ #endif
+
+ if (*fontPath != '\0')
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 2);
+ strcat(fontPath, ",");
+ }
+ else
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH) + 1);
+ }
+
+ strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH);
+ }
+
+ if (stat(NXAGENT_ALTERNATE_FONT_DIR_2, &dirStat) == 0 &&
+ S_ISDIR(dirStat.st_mode) != 0)
+ {
+ /*
+ * Let's use the "/usr/share/fonts/X11" path.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n",
+ validateString(NXAGENT_ALTERNATE_FONT_DIR_2));
+ #endif
+
+ if (*fontPath != '\0')
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 2);
+ strcat(fontPath, ",");
+ }
+ else
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_2) + 1);
+ }
+
+ strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_2);
+ }
+
+ if (stat(NXAGENT_ALTERNATE_FONT_DIR_3, &dirStat) == 0 &&
+ S_ISDIR(dirStat.st_mode) != 0)
+ {
+ /*
+ * Let's use the "/usr/X11R6/lib/X11/fonts" path.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Assuming fonts in directory [%s].\n",
+ validateString(NXAGENT_ALTERNATE_FONT_DIR_3));
+ #endif
+
+ if (*fontPath != '\0')
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 2);
+ strcat(fontPath, ",");
+ }
+ else
+ {
+ fontPath = realloc(fontPath, strlen(fontPath) + strlen(NXAGENT_ALTERNATE_FONT_PATH_3) + 1);
+ }
+
+ strcat(fontPath, NXAGENT_ALTERNATE_FONT_PATH_3);
+ }
+ if (*fontPath == '\0')
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Can't find a valid font directory.\n");
+
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: WARNING! Using font path [%s].\n",
+ validateString(defaultFontPath));
+ #endif
+ }
+ else
+ {
+ defaultFontPath = fontPath;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentVerifyDefaultFontPath: Using font path [%s].\n",
+ validateString(defaultFontPath));
+ #endif
+ }
+
+ return;
+}
+
+XFontStruct* nxagentLoadQueryFont(register Display *dpy, char *name, FontPtr pFont)
+{
+ XFontStruct* fs;
+ xCharInfo *xcip;
+
+ fs = (XFontStruct *) malloc (sizeof (XFontStruct));
+
+ if (fs == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontStruct.\n");
+ #endif
+
+ return (XFontStruct *)NULL;
+ }
+
+ #ifdef NXAGENT_RECONNECT_FONT_DEBUG
+ fprintf(stderr, "nxagentLoadQueryFont: Looking for font '%s'.\n", name);
+ #endif
+
+ if (nxagentFontLookUp(name) == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentLoadQueryFont: WARNING! Font not found '%s'.\n", name);
+ #endif
+
+ free(fs);
+
+ return (XFontStruct *) NULL;
+ }
+
+ fs -> ext_data = NULL; /* Hook for extension to hang data.*/
+ fs -> fid = XLoadFont(dpy, name); /* Font id for this font. */
+ fs -> direction = pFont->info.drawDirection; /* Hint about the direction font is painted. */
+ fs -> min_char_or_byte2 = pFont->info.firstCol; /* First character. */
+ fs -> max_char_or_byte2 = pFont->info.lastCol; /* Last character. */
+ fs -> min_byte1 = pFont->info.firstRow; /* First row that exists. */
+ fs -> max_byte1 = pFont->info.lastRow; /* Last row that exists. */
+ fs -> all_chars_exist = pFont->info.allExist; /* Flag if all characters have nonzero size. */
+ fs -> default_char = pFont->info.defaultCh; /* Char to print for undefined character. */
+ fs -> n_properties = pFont->info.nprops; /* How many properties there are. */
+
+ /*
+ * If no properties defined for the font, then it is bad
+ * font, but shouldn't try to read nothing.
+ */
+
+ if (fs -> n_properties > 0)
+ {
+ register long nbytes;
+
+ nbytes = pFont -> info.nprops * sizeof(XFontProp);
+ fs -> properties = (XFontProp *) malloc((unsigned) nbytes);
+
+ if (fs -> properties == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentLoadQueryFont: WARNING! Failed allocation of XFontProp.");
+ #endif
+
+ free((char *) fs);
+ return (XFontStruct *) NULL;
+ }
+
+ memmove(fs -> properties, pFont -> info.props, nbytes);
+ }
+
+ xcip = (xCharInfo *) &pFont -> info.ink_minbounds;
+
+ fs -> min_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing);
+ fs -> min_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing);
+ fs -> min_bounds.width = cvtINT16toShort(xcip -> characterWidth);
+ fs -> min_bounds.ascent = cvtINT16toShort(xcip -> ascent);
+ fs -> min_bounds.descent = cvtINT16toShort(xcip -> descent);
+ fs -> min_bounds.attributes = xcip -> attributes;
+
+ xcip = (xCharInfo *) &pFont -> info.ink_maxbounds;
+
+ fs -> max_bounds.lbearing = cvtINT16toShort(xcip -> leftSideBearing);
+ fs -> max_bounds.rbearing = cvtINT16toShort(xcip -> rightSideBearing);
+ fs -> max_bounds.width = cvtINT16toShort(xcip -> characterWidth);
+ fs -> max_bounds.ascent = cvtINT16toShort(xcip -> ascent);
+ fs -> max_bounds.descent = cvtINT16toShort(xcip -> descent);
+ fs -> max_bounds.attributes = xcip -> attributes;
+
+ fs -> per_char = NULL; /* First_char to last_char information. */
+ fs -> ascent = pFont->info.fontAscent; /* Logical extent above baseline for spacing. */
+ fs -> descent = pFont->info.fontDescent; /* Logical decent below baseline for spacing. */
+
+ return fs;
+}
+
+int nxagentFreeFont(XFontStruct *fs)
+{
+
+ if (fs -> per_char)
+ {
+ #ifdef USE_XF86BIGFONT
+ _XF86BigfontFreeFontMetrics(fs);
+ #else
+ free ((char *) fs->per_char);
+ #endif
+ }
+
+ if (fs -> properties)
+ {
+ free (fs->properties);
+ }
+
+ XFree(fs);
+
+ return 1;
+}
+
+
+int nxagentSplitString(char *string, char *fields[], int nfields, char *sep)
+{
+ int seplen;
+ int fieldlen;
+ int last;
+ int len;
+ int i;
+
+ char *current;
+ char *next;
+
+ seplen = strlen(sep);
+ len = strlen(string);
+
+ current = string;
+
+ i = 0;
+ last = 0;
+
+ for (;;)
+ {
+ next = NULL;
+
+ if (current < string + len)
+ {
+ next = strstr(current, sep);
+ }
+
+ if (next == NULL)
+ {
+ next = string + len;
+ last = 1;
+ }
+
+ fieldlen = next - current;
+
+ if (i < nfields)
+ {
+ fields[i] = (char *) malloc(fieldlen + 1);
+ strncpy(fields[i], current, fieldlen);
+ *(fields[i] + fieldlen) = 0;
+ }
+ else
+ {
+ fields[i] = NULL;
+ }
+
+ current = next + seplen;
+
+ i++;
+
+ if (last == 1)
+ {
+ break;
+ }
+ }
+
+ return i;
+}
+
+char *nxagentMakeScalableFontName(const char *fontName, int scalableResolution)
+{
+ char *scalableFontName;
+ const char *s;
+ int len;
+ int field;
+
+ len = strlen(fontName) + 1;
+
+ scalableFontName = malloc(len);
+
+ if (scalableFontName == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentMakeScalableFontName: PANIC! malloc() failed.\n");
+ #endif
+
+ return NULL;
+ }
+
+ scalableFontName[0] = 0;
+
+ if (*fontName != '-')
+ {
+ goto MakeScalableFontNameError;
+ }
+
+ s = fontName;
+
+ field = 0;
+
+ while (s != NULL)
+ {
+ s = strchr(s + 1, '-');
+
+ if (s != NULL)
+ {
+ if (field == 6 || field == 7 || field == 11)
+ {
+ /*
+ * PIXEL_SIZE || POINT_SIZE || AVERAGE_WIDTH
+ */
+
+ strcat(scalableFontName, "-0");
+ }
+ else if (scalableResolution == 1 && (field == 8 || field == 9))
+ {
+ /*
+ * RESOLUTION_X || RESOLUTION_Y
+ */
+
+ strcat(scalableFontName, "-0");
+ }
+ else
+ {
+ strncat(scalableFontName, fontName, s - fontName);
+ }
+
+ fontName = s;
+ }
+ else
+ {
+ strcat(scalableFontName, fontName);
+ }
+
+ field++;
+ }
+
+ if (field != 14)
+ {
+ goto MakeScalableFontNameError;
+ }
+
+ return scalableFontName;
+
+MakeScalableFontNameError:
+
+ free(scalableFontName);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMakeScalableFontName: Invalid font name.\n");
+ #endif
+
+ return NULL;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Font.h b/nx-X11/programs/Xserver/hw/nxagent/Font.h
new file mode 100644
index 000000000..c5b236562
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Font.h
@@ -0,0 +1,85 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Font_H__
+#define __Font_H__
+
+#include <X11/fonts/fontstruct.h>
+#include "resource.h"
+
+extern RESTYPE RT_NX_FONT;
+
+extern int nxagentFontPrivateIndex;
+
+typedef struct
+{
+ XFontStruct *font_struct;
+ char fontName[256];
+ XID mirrorID;
+} nxagentPrivFont;
+
+extern const int nxagentMaxFontNames;
+
+#define nxagentFontPriv(pFont) \
+ ((nxagentPrivFont *)FontGetPrivate(pFont, nxagentFontPrivateIndex))
+
+#define nxagentFontStruct(pFont) (nxagentFontPriv(pFont)->font_struct)
+
+#define nxagentFont(pFont) (nxagentFontStruct(pFont)->fid)
+
+Bool nxagentRealizeFont(ScreenPtr pScreen, FontPtr pFont);
+Bool nxagentUnrealizeFont(ScreenPtr pScreen, FontPtr pFont);
+
+void nxagentFreeFontCache(void);
+
+void nxagentListRemoteFonts(const char *searchPattern, const int maxNames);
+int nxagentFontLookUp(const char *name);
+Bool nxagentFontFind(const char *name, int *pos);
+void nxagentListRemoteAddName(const char *name, int status);
+
+int nxagentDestroyNewFontResourceType(void * p, XID id);
+
+Bool nxagentDisconnectAllFonts(void);
+Bool nxagentReconnectAllFonts(void *p0);
+
+void nxagentVerifyDefaultFontPath(void);
+
+int nxagentSplitString(char *string, char *fields[], int nfields, char *sep);
+
+#endif /* __Font_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/GC.c b/nx-X11/programs/Xserver/hw/nxagent/GC.c
new file mode 100644
index 000000000..abe66602a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GC.c
@@ -0,0 +1,1717 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+#include "dixstruct.h"
+#include <X11/fonts/fontstruct.h>
+#include "mistruct.h"
+#include "region.h"
+
+#include "Agent.h"
+
+#include "Display.h"
+#include "GCs.h"
+#include "GCOps.h"
+#include "Image.h"
+#include "Drawable.h"
+#include "Pixmaps.h"
+#include "Font.h"
+#include "Colormap.h"
+#include "Trap.h"
+#include "Screen.h"
+#include "Pixels.h"
+
+#include "../../fb/fb.h"
+
+RESTYPE RT_NX_GC;
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+int nxagentGCPrivateIndex;
+
+nxagentGraphicContextsPtr nxagentGraphicContexts;
+int nxagentGraphicContextsSize;
+
+void nxagentDisconnectGraphicContexts(void);
+GCPtr nxagentCreateGraphicContext(int depth);
+
+static void nxagentReconnectGC(void*, XID, void*);
+static void nxagentReconnectClip(GCPtr, int, void *, int);
+static int nxagentCompareRegions(RegionPtr, RegionPtr);
+
+struct nxagentGCRec
+{
+ GCPtr pGC;
+ XlibGC gc;
+ struct nxagentGCRec *next;
+};
+
+static struct
+{
+ struct nxagentGCRec *first;
+ struct nxagentGCRec *last;
+ int size;
+} nxagentGCList = { NULL, NULL, 0 };
+
+static struct nxagentGCRec *nxagentGetFirstGC(void);
+
+static void nxagentRestoreGCList(void);
+
+static GCFuncs nxagentFuncs =
+{
+ nxagentValidateGC,
+ nxagentChangeGC,
+ nxagentCopyGC,
+ nxagentDestroyGC,
+ nxagentChangeClip,
+ nxagentDestroyClip,
+ nxagentCopyClip,
+};
+
+static GCOps nxagentOps =
+{
+ nxagentFillSpans,
+ nxagentSetSpans,
+ nxagentPutImage,
+ nxagentCopyArea,
+ nxagentCopyPlane,
+ nxagentPolyPoint,
+ nxagentPolyLines,
+ nxagentPolySegment,
+ nxagentPolyRectangle,
+ nxagentPolyArc,
+ nxagentFillPolygon,
+ nxagentPolyFillRect,
+ nxagentPolyFillArc,
+ nxagentPolyText8,
+ nxagentPolyText16,
+ nxagentImageText8,
+ nxagentImageText16,
+ nxagentImageGlyphBlt,
+ nxagentPolyGlyphBlt,
+ nxagentPushPixels
+};
+
+Bool nxagentCreateGC(GCPtr pGC)
+{
+ FbGCPrivPtr pPriv;
+
+ pGC->clientClipType = CT_NONE;
+ pGC->clientClip = NULL;
+
+ pGC->funcs = &nxagentFuncs;
+ pGC->ops = &nxagentOps;
+
+ pGC->miTranslate = 1;
+
+ if (pGC -> stipple && !nxagentPixmapIsVirtual(pGC -> stipple))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreateGC: GC at [%p] got real stipple at [%p] switched to virtual.\n",
+ (void*)pGC, (void*)pGC -> stipple);
+ #endif
+
+ pGC -> stipple = nxagentVirtualPixmap(pGC -> stipple);
+ }
+
+ /*
+ * We create the GC based on the default
+ * drawables. The proxy knows this and
+ * optimizes the encoding of the create
+ * GC message to include the id of the
+ * drawable in the checksum.
+ */
+
+ nxagentGCPriv(pGC)->gc = XCreateGC(nxagentDisplay,
+ nxagentDefaultDrawables[pGC->depth],
+ 0L, NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateGC: GC [%p]\n", (void *) pGC);
+ #endif
+
+ pPriv = (pGC)->devPrivates[fbGCPrivateIndex].ptr;
+
+ fbGetRotatedPixmap(pGC) = 0;
+ fbGetExpose(pGC) = 1;
+ fbGetFreeCompClip(pGC) = 0;
+ fbGetCompositeClip(pGC) = 0;
+
+ pPriv->bpp = BitsPerPixel (pGC->depth);
+
+ nxagentGCPriv(pGC)->nClipRects = 0;
+
+ memset(&(nxagentGCPriv(pGC) -> lastServerValues), 0, sizeof(XGCValues));
+
+ /*
+ * Init to default GC values.
+ */
+
+ nxagentGCPriv(pGC) -> lastServerValues.background = 1;
+
+ nxagentGCPriv(pGC) -> lastServerValues.plane_mask = ~0;
+
+ nxagentGCPriv(pGC) -> lastServerValues.graphics_exposures = 1;
+
+ nxagentGCPriv(pGC) -> lastServerValues.dashes = 4;
+
+ nxagentGCPriv(pGC) -> mid = FakeClientID(serverClient -> index);
+
+ nxagentGCPriv(pGC) -> pPixmap = NULL;
+
+ AddResource(nxagentGCPriv(pGC) -> mid, RT_NX_GC, (void *) pGC);
+
+ return True;
+}
+
+void nxagentValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ PixmapPtr lastTile, lastStipple;
+
+ DrawablePtr pVirtual = (pDrawable -> type == DRAWABLE_PIXMAP) ?
+ nxagentVirtualDrawable(pDrawable) :
+ pDrawable;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateGC: Going to validate GC at [%p] for drawable at [%p] with changes [%lx].\n",
+ (void *) pGC, (void *) pDrawable, changes);
+ #endif
+
+ pGC->lastWinOrg.x = pDrawable->x;
+ pGC->lastWinOrg.y = pDrawable->y;
+
+ if (!pGC -> tileIsPixel && !nxagentPixmapIsVirtual(pGC -> tile.pixmap))
+ {
+ pGC -> tile.pixmap = nxagentVirtualPixmap(pGC -> tile.pixmap);
+ }
+
+ lastTile = pGC -> tile.pixmap;
+
+ lastStipple = pGC->stipple;
+
+ if (lastStipple)
+ {
+ pGC->stipple = nxagentVirtualPixmap(pGC->stipple);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateGC: Drawable at [%p] has type [%s] virtual [%p] bits per pixel [%d].\n",
+ (void *) pDrawable, (pDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
+ (void *) pVirtual, pVirtual -> bitsPerPixel);
+ #endif
+
+ if (pVirtual -> bitsPerPixel == 0)
+ {
+ /*
+ * Don't enter fbValidateGC() with 0 bpp
+ * or agent will block in a endless loop.
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentValidateGC: WARNING! Virtual drawable at [%p] has invalid bits per pixel.\n",
+ (void *) pVirtual);
+
+ fprintf(stderr, "nxagentValidateGC: WARNING! While validating GC at [%p] for drawable at [%p] with changes [%lx].\n",
+ (void *) pGC, (void *) pDrawable, changes);
+
+ fprintf(stderr, "nxagentValidateGC: WARNING! Bad drawable at [%p] has type [%s] virtual [%p] bits per pixel [%d].\n",
+ (void *) pDrawable, (pDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
+ (void *) pVirtual, pVirtual -> bitsPerPixel);
+ #endif
+ }
+ else
+ {
+ fbValidateGC(pGC, changes, pVirtual);
+ }
+
+ if (pGC->tile.pixmap != lastTile)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentValidateGC: WARNING! Transforming pixmap at [%p] virtual at [%p] "
+ "in virtual pixmap.\n", (void *) nxagentPixmapPriv(pGC -> tile.pixmap) -> pRealPixmap,
+ (void *) nxagentPixmapPriv(pGC -> tile.pixmap) -> pRealPixmap);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateGC: GC [%p] new tile [%p] from fb set as virtual\n",
+ (void *) pGC, (void *) pGC->tile.pixmap);
+ #endif
+
+ nxagentPixmapIsVirtual(pGC->tile.pixmap) = True;
+ nxagentRealPixmap(pGC->tile.pixmap) = nxagentRealPixmap(lastTile);
+
+ if (nxagentRealPixmap(lastTile))
+ {
+ nxagentPixmapPriv(nxagentRealPixmap(lastTile))->pVirtualPixmap = pGC->tile.pixmap;
+ }
+ }
+
+ pGC->stipple = lastStipple;
+}
+
+void nxagentChangeGC(GCPtr pGC, unsigned long mask)
+{
+ #ifdef TEST
+ static int nDiscarded;
+ #endif
+
+ XGCValues values;
+
+ int changeFlag = 0;
+
+ if (mask & GCFunction)
+ {
+ values.function = pGC->alu;
+
+ changeFlag |= nxagentTestGC(values.function, function);
+ }
+
+ if (mask & GCPlaneMask)
+ {
+ values.plane_mask = pGC->planemask;
+
+ changeFlag += nxagentTestGC(values.plane_mask, plane_mask);
+ }
+
+ if (mask & GCForeground)
+ {
+ values.foreground = nxagentPixel(pGC->fgPixel);
+
+ changeFlag += nxagentTestGC(values.foreground, foreground);
+ }
+
+ if (mask & GCBackground)
+ {
+ values.background = nxagentPixel(pGC->bgPixel);
+
+ changeFlag += nxagentTestGC(values.background, background);
+ }
+
+ if (mask & GCLineWidth)
+ {
+ values.line_width = pGC->lineWidth;
+
+ changeFlag += nxagentTestGC(values.line_width, line_width);
+ }
+
+ if (mask & GCLineStyle)
+ {
+ values.line_style = pGC->lineStyle;
+
+ changeFlag += nxagentTestGC(values.line_style, line_style);
+ }
+
+ if (mask & GCCapStyle)
+ {
+ values.cap_style = pGC->capStyle;
+
+ changeFlag += nxagentTestGC(values.cap_style, cap_style);
+ }
+
+ if (mask & GCJoinStyle)
+ {
+ values.join_style = pGC->joinStyle;
+
+ changeFlag += nxagentTestGC(values.join_style, join_style);
+ }
+
+ if (mask & GCFillStyle)
+ {
+ values.fill_style = pGC->fillStyle;
+
+ changeFlag += nxagentTestGC(values.fill_style, fill_style);
+ }
+
+ if (mask & GCFillRule)
+ {
+ values.fill_rule = pGC->fillRule;
+
+ changeFlag += nxagentTestGC(values.fill_rule, fill_rule);
+ }
+
+ if (mask & GCTile)
+ {
+ if (pGC->tileIsPixel)
+ {
+ mask &= ~GCTile;
+ }
+ else
+ {
+ if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized &&
+ nxagentGCTrap == 0)
+ {
+ /*
+ * If the tile is corrupted and is not too
+ * much large, it can be synchronized imme-
+ * diately. In the other cases, the tile is
+ * cleared with a solid color to become usa-
+ * ble. This approach should solve the high
+ * delay on slow links waiting for a back-
+ * ground tile to be synchronized.
+ */
+
+ if (nxagentOption(DeferLevel) >= 2 &&
+ (pGC -> tile.pixmap -> drawable.width > 240 ||
+ pGC -> tile.pixmap -> drawable.height > 240))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: WARNING! Going to fill with solid color the corrupted tile at [%p] "
+ "for GC at [%p] with size [%dx%d].\n", (void *) pGC -> tile.pixmap, (void *)pGC,
+ ((DrawablePtr) pGC -> tile.pixmap) -> width, ((DrawablePtr) pGC -> tile.pixmap) -> height);
+ #endif
+
+ nxagentFillRemoteRegion((DrawablePtr) pGC -> tile.pixmap, nxagentCorruptedRegion((DrawablePtr) pGC -> tile.pixmap));
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: WARNING! Synchronizing GC at [%p] due the tile at [%p] with size [%dx%d].\n",
+ (void *)pGC, (void *)pGC -> tile.pixmap, ((DrawablePtr) pGC -> tile.pixmap) -> width,
+ ((DrawablePtr) pGC -> tile.pixmap) -> height);
+ #endif
+
+ nxagentSynchronizeDrawable((DrawablePtr) pGC -> tile.pixmap, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ values.tile = nxagentPixmap(pGC->tile.pixmap);
+
+ pGC->tile.pixmap = nxagentVirtualPixmap(pGC->tile.pixmap);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: New tile on GC [%p] tile is [%p]\n",
+ (void *) pGC, (void *) pGC->tile.pixmap);
+ #endif
+
+ changeFlag += nxagentTestGC(values.tile, tile);
+ }
+ }
+
+ if (mask & GCStipple)
+ {
+ if (nxagentDrawableStatus((DrawablePtr) pGC -> stipple) == NotSynchronized &&
+ nxagentGCTrap == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: WARNING! Synchronizing GC at [%p] due the stipple at [%p].\n",
+ (void *)pGC, (void *)pGC -> stipple);
+ #endif
+
+ nxagentSynchronizeDrawable((DrawablePtr) pGC -> stipple, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ values.stipple = nxagentPixmap(pGC->stipple);
+
+ pGC->stipple = nxagentVirtualPixmap(pGC->stipple);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: New stipple on GC [%p] stipple is [%p]\n",
+ (void *) pGC, (void *) pGC->stipple);
+ #endif
+
+ changeFlag += nxagentTestGC(values.stipple, stipple);
+ }
+
+ if (mask & GCTileStipXOrigin)
+ {
+ values.ts_x_origin = pGC->patOrg.x;
+
+ changeFlag += nxagentTestGC(values.ts_x_origin, ts_x_origin);
+ }
+
+ if (mask & GCTileStipYOrigin)
+ {
+ values.ts_y_origin = pGC->patOrg.y;
+
+ changeFlag += nxagentTestGC(values.ts_y_origin, ts_y_origin);
+ }
+
+ if (mask & GCFont)
+ {
+ if (!nxagentFontStruct(pGC -> font))
+ {
+ mask &= ~GCFont;
+ }
+ else
+ {
+ values.font = nxagentFont(pGC->font);
+
+ changeFlag += nxagentTestGC(values.font, font);
+ }
+ }
+
+ if (mask & GCSubwindowMode)
+ {
+ values.subwindow_mode = pGC->subWindowMode;
+
+ changeFlag += nxagentTestGC(values.subwindow_mode, subwindow_mode);
+ }
+
+ if (mask & GCGraphicsExposures)
+ {
+ values.graphics_exposures = pGC->graphicsExposures;
+
+ changeFlag += nxagentTestGC(values.graphics_exposures, graphics_exposures);
+ }
+
+ if (mask & GCClipXOrigin)
+ {
+ values.clip_x_origin = pGC->clipOrg.x;
+
+ changeFlag += nxagentTestGC(values.clip_x_origin, clip_x_origin);
+ }
+
+ if (mask & GCClipYOrigin)
+ {
+ values.clip_y_origin = pGC->clipOrg.y;
+
+ changeFlag += nxagentTestGC(values.clip_y_origin, clip_y_origin);
+ }
+
+ if (mask & GCClipMask)
+ {
+ /*
+ * This is handled in the change clip.
+ */
+
+ mask &= ~GCClipMask;
+ }
+
+ if (mask & GCDashOffset)
+ {
+ values.dash_offset = pGC->dashOffset;
+
+ changeFlag += nxagentTestGC(values.dash_offset, dash_offset);
+ }
+
+ if (mask & GCDashList)
+ {
+ mask &= ~GCDashList;
+
+ if (nxagentGCTrap == 0)
+ {
+ XSetDashes(nxagentDisplay, nxagentGC(pGC),
+ pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList);
+ }
+ }
+
+ if (mask & GCArcMode)
+ {
+ values.arc_mode = pGC->arcMode;
+
+ changeFlag += nxagentTestGC(values.arc_mode, arc_mode);
+ }
+
+ if (nxagentGCTrap == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeGC: Skipping change of GC at [%p] on the real X server.\n",
+ (void *) pGC);
+ #endif
+
+ return;
+ }
+
+ if (mask && changeFlag)
+ {
+ XChangeGC(nxagentDisplay, nxagentGC(pGC), mask, &values);
+ }
+ #ifdef TEST
+ else if (mask)
+ {
+ fprintf(stderr, "nxagentChangeGC: Discarded [%d] Mask [%lu]\n", ++nDiscarded, mask);
+ }
+ #endif
+}
+
+void nxagentCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyGC: Copying the GC with source at [%p] destination "
+ "at [%p] mask [%lu].\n", pGCSrc, pGCDst, mask);
+ #endif
+
+ /*
+ * The MI function doesn't do anything.
+ *
+ * miCopyGC(pGCSrc, mask, pGCDst);
+ */
+
+ XCopyGC(nxagentDisplay, nxagentGC(pGCSrc), mask, nxagentGC(pGCDst));
+
+ /*
+ * Copy the private foreground field
+ * of the GC if GCForeground is set.
+ */
+
+ nxagentCopyGCPriv(GCForeground,foreground,pGCSrc,mask,pGCDst);
+}
+
+void nxagentDestroyGC(GCPtr pGC)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyGC: GC at [%p].\n", (void *) pGC);
+ #endif
+
+ if (nxagentGCPriv(pGC) -> mid != 0)
+ {
+ FreeResource(nxagentGCPriv(pGC) -> mid, RT_NONE);
+ }
+
+ XFreeGC(nxagentDisplay, nxagentGC(pGC));
+
+ miDestroyGC(pGC);
+}
+
+void nxagentChangeClip(GCPtr pGC, int type, void * pValue, int nRects)
+{
+ int i, size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+ int clipsMatch = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeClip: Going to change clip on GC [%p]\n",
+ (void *) pGC);
+ #endif
+
+ switch (type)
+ {
+ case CT_NONE:
+ {
+ clipsMatch = (pGC -> clientClipType == None);
+
+ break;
+ }
+ case CT_REGION:
+ {
+ clipsMatch = nxagentCompareRegions(pGC -> clientClip, (RegionPtr) pValue);
+
+ break;
+ }
+ case CT_UNSORTED:
+ case CT_YSORTED:
+ case CT_YXSORTED:
+ case CT_YXBANDED:
+ {
+ RegionPtr pReg = RegionFromRects(nRects, (xRectangle *)pValue, type);
+
+ clipsMatch = nxagentCompareRegions(pGC -> clientClip, pReg);
+
+ RegionDestroy(pReg);
+
+ break;
+ }
+ default:
+ {
+ clipsMatch = 0;
+
+ break;
+ }
+ }
+
+ nxagentDestroyClipHelper(pGC);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeClip: Type [%d] regions clipsMatch [%d].\n",
+ type, clipsMatch);
+ #endif
+
+ switch (type)
+ {
+ case CT_NONE:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC), None);
+ }
+
+ break;
+ }
+ case CT_REGION:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ nRects = RegionNumRects((RegionPtr)pValue);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) malloc(size);
+ pBox = RegionRects((RegionPtr)pValue);
+
+ for (i = nRects; i-- > 0;)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y,
+ pRects, nRects, Unsorted);
+ free((char *) pRects);
+ }
+
+ break;
+ }
+ case CT_PIXMAP:
+ {
+ if (nxagentGCTrap == 0)
+ {
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC),
+ nxagentPixmap((PixmapPtr)pValue));
+ }
+
+ pGC->clientClip = (void *) (*pGC->pScreen->BitmapToRegion)((PixmapPtr) pValue);
+
+ nxagentGCPriv(pGC)->pPixmap = (PixmapPtr)pValue;
+
+ pValue = pGC->clientClip;
+
+ type = CT_REGION;
+
+ break;
+ }
+ case CT_UNSORTED:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, Unsorted);
+ }
+
+ break;
+ }
+ case CT_YSORTED:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YSorted);
+ }
+
+ break;
+ }
+ case CT_YXSORTED:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YXSorted);
+ }
+
+ break;
+ }
+ case CT_YXBANDED:
+ {
+ if (clipsMatch == 0 && nxagentGCTrap == 0)
+ {
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YXBanded);
+ }
+
+ break;
+ }
+ }
+
+ switch(type)
+ {
+ case CT_UNSORTED:
+ case CT_YSORTED:
+ case CT_YXSORTED:
+ case CT_YXBANDED:
+ {
+ /*
+ * Other parts of the server can only
+ * deal with CT_NONE, CT_PIXMAP and
+ * CT_REGION client clips.
+ */
+
+ pGC->clientClip = (void *) RegionFromRects(nRects,
+ (xRectangle *)pValue, type);
+ free(pValue);
+
+ pValue = pGC->clientClip;
+
+ type = CT_REGION;
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ pGC->clientClipType = type;
+ pGC->clientClip = pValue;
+
+ nxagentGCPriv(pGC)->nClipRects = nRects;
+}
+
+void nxagentDestroyClip(GCPtr pGC)
+{
+ miDestroyClip(pGC);
+
+ if (pGC->clientClipType == CT_PIXMAP)
+ {
+ (*pGC->pScreen->DestroyPixmap)((PixmapPtr) (pGC->clientClip));
+ }
+
+ nxagentDestroyClipHelper(pGC);
+
+ if (nxagentGCTrap == 0)
+ {
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC), None);
+ }
+
+ pGC->clientClipType = CT_NONE;
+ pGC->clientClip = NULL;
+
+ nxagentGCPriv(pGC)->nClipRects = 0;
+}
+
+void nxagentDestroyClipHelper(GCPtr pGC)
+{
+ switch (pGC->clientClipType)
+ {
+ default:
+ case CT_NONE:
+ break;
+ case CT_REGION:
+ RegionDestroy(pGC->clientClip);
+ break;
+ case CT_PIXMAP:
+ nxagentDestroyPixmap((PixmapPtr)pGC->clientClip);
+ break;
+ }
+
+ if (nxagentGCPriv(pGC)->pPixmap != NULL)
+ {
+ nxagentDestroyPixmap(nxagentGCPriv(pGC)->pPixmap);
+ nxagentGCPriv(pGC)->pPixmap = NULL;
+ }
+}
+
+void nxagentCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
+{
+ RegionPtr pRgn;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyClip: Going to copy clip from GC [%p] to GC [%p]\n",
+ (void *) pGCDst, (void *) pGCSrc);
+ #endif
+
+ switch (pGCSrc->clientClipType)
+ {
+ case CT_REGION:
+ if (nxagentGCPriv(pGCSrc)->pPixmap == NULL)
+ {
+ pRgn = RegionCreate(NULL, 1);
+ RegionCopy(pRgn, pGCSrc->clientClip);
+ nxagentChangeClip(pGCDst, CT_REGION, pRgn, 0);
+ }
+ else
+ {
+ nxagentGCPriv(pGCSrc)->pPixmap->refcnt++;
+
+ nxagentChangeClip(pGCDst, CT_PIXMAP, nxagentGCPriv(pGCSrc)->pPixmap, 0);
+ }
+ break;
+ case CT_PIXMAP:
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyClip: WARNING! Not incrementing counter for virtual pixmap at [%p].\n",
+ (void *) nxagentVirtualPixmap((PixmapPtr) pGCSrc->clientClip));
+ #endif
+
+ ((PixmapPtr) pGCSrc->clientClip)->refcnt++;
+
+ nxagentChangeClip(pGCDst, CT_PIXMAP, pGCSrc->clientClip, 0);
+
+ break;
+
+ case CT_NONE:
+ nxagentDestroyClip(pGCDst);
+ break;
+
+ }
+}
+
+static struct nxagentGCRec *nxagentGetFirstGC()
+{
+ struct nxagentGCRec *tmp = nxagentGCList.first;
+
+ if (nxagentGCList.size)
+ {
+ nxagentGCList.first = nxagentGCList.first -> next;
+ nxagentGCList.size--;
+
+ if (nxagentGCList.size == 0)
+ {
+ nxagentGCList.last = NULL;
+ }
+ }
+
+ return tmp;
+}
+
+static void nxagentFreeGCRec(struct nxagentGCRec *t)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGCRec: Freeing record at %p GC freed at %p.\n",
+ (void *) t, (void *) t -> gc);
+ #endif
+
+ free(t -> gc);
+
+ free(t);
+}
+
+static void nxagentRestoreGCRec(struct nxagentGCRec *t)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentRestoreGCRec: Freeing record at %p GC freed at %p.\n",
+ (void*)t, (void*)t -> gc);
+ #endif
+
+ if (nxagentGC(t -> pGC))
+ {
+ free(nxagentGC(t -> pGC));
+ }
+
+ nxagentGC(t -> pGC) = t -> gc;
+
+ free(t);
+}
+
+static void nxagentAddGCToList(GCPtr pGC)
+{
+ struct nxagentGCRec *tempGC = malloc(sizeof(struct nxagentGCRec));
+
+ if (tempGC == NULL)
+ {
+ FatalError("nxagentAddGCToList: malloc failed.");
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddGCToList: Adding GC %p to list at memory %p list size is %d.\n",
+ (void *) pGC, (void *) tempGC, nxagentGCList.size);
+ #endif
+
+ tempGC -> pGC = pGC;
+ tempGC -> gc = nxagentGC(pGC);
+ tempGC -> next = NULL;
+
+ if (nxagentGCList.size == 0 || nxagentGCList.first == NULL || nxagentGCList.last == NULL)
+ {
+ nxagentGCList.first = tempGC;
+ }
+ else
+ {
+ nxagentGCList.last -> next = tempGC;
+ }
+
+ nxagentGCList.last = tempGC;
+ nxagentGCList.size++;
+}
+
+void nxagentFreeGCList()
+{
+ struct nxagentGCRec *tempGC;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGCList: List size is %d first elt at %p last elt at %p.\n",
+ nxagentGCList.size, (void*)nxagentGCList.first, (void*)nxagentGCList.last);
+ #endif
+
+ while ((tempGC = nxagentGetFirstGC()))
+ {
+ nxagentFreeGCRec(tempGC);
+ }
+}
+
+static void nxagentRestoreGCList()
+{
+ struct nxagentGCRec *tempGC;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRestoreGCList: List size is %d first elt at %p last elt at %p.\n",
+ nxagentGCList.size, (void*)nxagentGCList.first, (void*)nxagentGCList.last);
+ #endif
+
+ while ((tempGC = nxagentGetFirstGC()))
+ {
+ nxagentRestoreGCRec(tempGC);
+ }
+}
+
+int nxagentDestroyNewGCResourceType(void * p, XID id)
+{
+ /*
+ * Address of the destructor is set in Init.c.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyNewGCResourceType: Destroying mirror id [%ld] for GC at [%p].\n",
+ nxagentGCPriv((GCPtr) p) -> mid, (void *) p);
+ #endif
+
+ nxagentGCPriv((GCPtr) p) -> mid = None;
+
+ return 1;
+}
+
+static void nxagentReconnectGC(void *param0, XID param1, void * param2)
+{
+ XGCValues values;
+ unsigned long valuemask;
+ GCPtr pGC = (GCPtr) param0;
+ Bool *pBool = (Bool*)param2;
+
+ if (pGC == NULL || !*pBool)
+ {
+ return;
+ }
+
+ if (nxagentGC(pGC))
+ {
+ nxagentAddGCToList(pGC);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectGC: GCRec %p doesn't have a valid pointer to GC data.\n", (void*)pGC);
+ #endif
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectGC: GC at [%p].\n", (void *) pGC);
+ #endif
+
+ valuemask = 0;
+ memset(&values,0,sizeof(XGCValues));
+ values.function = pGC->alu;
+ valuemask |= GCFunction;
+ values.plane_mask = pGC->planemask;
+ valuemask |= GCPlaneMask;
+ values.foreground = nxagentPixel(pGC->fgPixel);
+ valuemask |= GCForeground;
+ values.background = nxagentPixel(pGC->bgPixel);
+ valuemask |= GCBackground;
+
+ values.line_width = pGC->lineWidth;
+ valuemask |= GCLineWidth;
+ values.line_style = pGC->lineStyle;
+ valuemask |= GCLineStyle;
+ values.cap_style = pGC->capStyle;
+ valuemask |= GCCapStyle;
+ values.join_style = pGC->joinStyle;
+ valuemask |= GCJoinStyle;
+ values.fill_style = pGC->fillStyle;
+ valuemask |= GCFillStyle;
+ values.fill_rule = pGC->fillRule;
+ valuemask |= GCFillRule;
+
+ if (!pGC -> tileIsPixel && (pGC -> tile.pixmap != NULL))
+ {
+ if (nxagentPixmapIsVirtual(pGC -> tile.pixmap))
+ {
+ values.tile = nxagentPixmap(nxagentRealPixmap(pGC -> tile.pixmap));
+ }
+ else
+ {
+ values.tile = nxagentPixmap(pGC -> tile.pixmap);
+ }
+
+ valuemask |= GCTile;
+ }
+
+ if (pGC->stipple != NULL)
+ {
+ if (nxagentPixmapIsVirtual(pGC -> stipple))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectGC: Reconnecting virtual stipple [%p] for GC [%p].\n",
+ (void *) pGC -> stipple, (void *) pGC);
+ #endif
+
+ if (nxagentPixmap(nxagentRealPixmap(pGC -> stipple)) == 0)
+ {
+ nxagentReconnectPixmap(nxagentRealPixmap(pGC -> stipple), 0, pBool);
+ }
+
+ values.stipple = nxagentPixmap(nxagentRealPixmap(pGC -> stipple));
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectGC: Reconnecting stipple [%p] for GC [%p].\n",
+ (void *) pGC -> stipple, (void *) pGC);
+ #endif
+
+ if (nxagentPixmap(pGC -> stipple) == 0)
+ {
+ nxagentReconnectPixmap(pGC -> stipple, 0, pBool);
+ }
+
+ values.stipple = nxagentPixmap(pGC->stipple);
+ }
+ valuemask |= GCStipple;
+ }
+
+ values.ts_x_origin = pGC->patOrg.x;
+ valuemask |= GCTileStipXOrigin;
+ values.ts_y_origin = pGC->patOrg.y;
+ valuemask |= GCTileStipYOrigin;
+
+ if (pGC->font != NULL)
+ {
+ values.font = nxagentFont(pGC->font);
+ valuemask |= GCFont;
+ }
+
+ values.subwindow_mode = pGC->subWindowMode;
+ valuemask |= GCSubwindowMode;
+ values.graphics_exposures = pGC->graphicsExposures;
+ valuemask |= GCGraphicsExposures;
+ values.clip_x_origin = pGC->clipOrg.x;
+ valuemask |= GCClipXOrigin;
+ values.clip_y_origin = pGC->clipOrg.y;
+ valuemask |= GCClipYOrigin;
+ valuemask |= GCClipMask;
+ values.dash_offset = pGC->dashOffset;
+ valuemask |= GCDashOffset;
+
+ if (pGC->dash != NULL)
+ {
+ values.dashes = *pGC->dash;
+ valuemask |= GCDashList;
+ }
+
+ values.arc_mode = pGC->arcMode;
+ valuemask |= GCArcMode;
+
+ if ((nxagentGC(pGC) = XCreateGC(nxagentDisplay,
+ nxagentDefaultDrawables[pGC->depth],
+ valuemask, &values)) == NULL)
+ {
+ *pBool = False;
+ }
+
+ nxagentReconnectClip(pGC,
+ pGC -> clientClipType,
+ pGC -> clientClip, nxagentGCPriv(pGC) -> nClipRects);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+}
+
+Bool nxagentReconnectAllGCs(void *p0)
+{
+ int cid;
+ Bool GCSuccess = True;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectAllGCs\n");
+ #endif
+
+ /*
+ * The resource type RT_NX_GC is created on the
+ * server client only, so we can avoid to loop
+ * through all the clients.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_GC, nxagentReconnectGC, &GCSuccess);
+
+ for (cid = 0; (cid < MAXCLIENTS) && GCSuccess; cid++)
+ {
+ if (clients[cid])
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllGCs: Going to reconnect GC of client [%d].\n", cid);
+ #endif
+
+ FindClientResourcesByType(clients[cid], RT_GC, nxagentReconnectGC, &GCSuccess);
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllGCs: GCs reconnection completed.\n");
+ #endif
+
+ return GCSuccess;
+}
+
+void nxagentDisconnectGC(void * p0, XID x1, void * p2)
+{
+ GCPtr pGC = (GCPtr) p0;
+ Bool* pBool = (Bool*) p2;
+
+ if (!*pBool || !pGC)
+ {
+ if (!pGC)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentDisconnectGC: WARNING! pGC is NULL.\n");
+ #endif
+ }
+
+ return;
+ }
+
+ if (pGC -> stipple)
+ {
+ PixmapPtr pMap = pGC -> stipple;
+
+ nxagentDisconnectPixmap(nxagentRealPixmap(pMap), 0, pBool);
+ }
+}
+
+Bool nxagentDisconnectAllGCs()
+{
+ int cid;
+ Bool success = True;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisconnectAllGCs\n");
+ #endif
+
+ /*
+ * The resource type RT_NX_GC is created on the
+ * server client only, so we can avoid to loop
+ * through all the clients.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_GC,
+ (FindResType) nxagentDisconnectGC, &success);
+
+ for (cid = 0; (cid < MAXCLIENTS) && success; cid++)
+ {
+ if (clients[cid])
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllGCs: Going to disconnect GC of client [%d].\n", cid);
+ #endif
+
+ FindClientResourcesByType(clients[cid], RT_GC,
+ (FindResType) nxagentDisconnectGC, &success);
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllGCs: GCs disconnection completed.\n");
+ #endif
+
+ nxagentRestoreGCList();
+
+ nxagentDisconnectGraphicContexts();
+
+ return success;
+}
+
+static void nxagentReconnectClip(GCPtr pGC, int type, void * pValue, int nRects)
+{
+ int i, size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectClip: going to change clip on GC [%p]\n",
+ (void *) pGC);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectClip: Type is [%s].\n", (type == CT_NONE) ?
+ "CT_NONE" : (type == CT_REGION) ? "CT_REGION" : (type == CT_PIXMAP) ?
+ "CT_REGION" : "UNKNOWN");
+ #endif
+
+ switch(type)
+ {
+ case CT_NONE:
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC), None);
+ break;
+
+ case CT_REGION:
+ if (nxagentGCPriv(pGC)->pPixmap == NULL)
+ {
+ nRects = RegionNumRects((RegionPtr)pValue);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) malloc(size);
+ pBox = RegionRects((RegionPtr)pValue);
+ for (i = nRects; i-- > 0;) {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ /*
+ * Originally, the clip origin area were 0,0
+ * but it didn't work with kedit and family,
+ * because it got the clip mask of the pixmap
+ * all traslated.
+ */
+
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y,
+ pRects, nRects, Unsorted);
+ free((char *) pRects);
+ }
+ else
+ {
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC),
+ nxagentPixmap(nxagentGCPriv(pGC)->pPixmap));
+
+ XSetClipOrigin(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y);
+ }
+
+ break;
+
+ case CT_PIXMAP:
+
+ XSetClipMask(nxagentDisplay, nxagentGC(pGC),
+ nxagentPixmap((PixmapPtr)pValue));
+
+ XSetClipOrigin(nxagentDisplay, nxagentGC(pGC), pGC -> clipOrg.x, pGC -> clipOrg.y);
+
+ pGC->clientClip = (void *) (*pGC->pScreen->BitmapToRegion)((PixmapPtr) pValue);
+
+ nxagentGCPriv(pGC)->pPixmap = (PixmapPtr)pValue;
+
+ pValue = pGC->clientClip;
+
+ type = CT_REGION;
+
+ break;
+
+ case CT_UNSORTED:
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, Unsorted);
+ break;
+
+ case CT_YSORTED:
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YSorted);
+ break;
+
+ case CT_YXSORTED:
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YXSorted);
+ break;
+
+ case CT_YXBANDED:
+ XSetClipRectangles(nxagentDisplay, nxagentGC(pGC),
+ pGC->clipOrg.x, pGC->clipOrg.y,
+ (XRectangle *)pValue, nRects, YXBanded);
+ break;
+ }
+
+ switch(type)
+ {
+ default:
+ break;
+
+ case CT_UNSORTED:
+ case CT_YSORTED:
+ case CT_YXSORTED:
+ case CT_YXBANDED:
+
+ /*
+ * other parts of server can only deal with CT_NONE,
+ * CT_PIXMAP and CT_REGION client clips.
+ */
+
+ pGC->clientClip = (void *) RegionFromRects(nRects,
+ (xRectangle *)pValue, type);
+ free(pValue);
+ pValue = pGC->clientClip;
+ type = CT_REGION;
+
+ break;
+ }
+
+ pGC->clientClipType = type;
+ pGC->clientClip = pValue;
+
+ nxagentGCPriv(pGC)->nClipRects = nRects;
+}
+
+static int nxagentCompareRegions(RegionPtr r1, RegionPtr r2)
+{
+ int i;
+
+ /*
+ * It returns 1 if regions are equal, 0 otherwise
+ */
+
+ if (r1 == NULL && r2 == NULL)
+ {
+ return 1;
+ }
+
+ if ((r1 == NULL) || (r2 == NULL))
+ {
+ return 0;
+ }
+
+ if (RegionNumRects(r1) != RegionNumRects(r2))
+ {
+ return 0;
+ }
+ else if (RegionNumRects(r1) == 0)
+ {
+ return 1;
+ }
+ else if ((*RegionExtents(r1)).x1 != (*RegionExtents(r2)).x1) return 0;
+ else if ((*RegionExtents(r1)).x2 != (*RegionExtents(r2)).x2) return 0;
+ else if ((*RegionExtents(r1)).y1 != (*RegionExtents(r2)).y1) return 0;
+ else if ((*RegionExtents(r1)).y2 != (*RegionExtents(r2)).y2) return 0;
+ else
+ {
+ for (i = 0; i < RegionNumRects(r1); i++)
+ {
+ if (RegionRects(r1)[i].x1 != RegionRects(r2)[i].x1) return 0;
+ else if (RegionRects(r1)[i].x2 != RegionRects(r2)[i].x2) return 0;
+ else if (RegionRects(r1)[i].y1 != RegionRects(r2)[i].y1) return 0;
+ else if (RegionRects(r1)[i].y2 != RegionRects(r2)[i].y2) return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * This function have to be called in the place
+ * of GetScratchGC if the GC will be used to per-
+ * form operations also on the remote X Server.
+ * This is why we call the XChangeGC at the end of
+ * the function.
+ */
+GCPtr nxagentGetScratchGC(unsigned depth, ScreenPtr pScreen)
+{
+ GCPtr pGC;
+ XGCValues values;
+ unsigned long mask;
+ int nxagentSaveGCTrap;
+
+ /*
+ * The GC trap is temporarily disabled in
+ * order to allow the remote clipmask reset
+ * requested by GetScratchGC().
+ */
+
+ nxagentSaveGCTrap = nxagentGCTrap;
+
+ nxagentGCTrap = 0;
+
+ pGC = GetScratchGC(depth, pScreen);
+
+ nxagentGCTrap = nxagentSaveGCTrap;
+
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGetScratchGC: Failed to retrieve the scratch GC.\n");
+ #endif
+
+ return NULL;
+ }
+
+ mask = 0;
+
+ values.function = pGC -> alu;
+ mask |= GCFunction;
+
+ values.plane_mask = pGC -> planemask;
+ mask |= GCPlaneMask;
+
+ values.foreground = nxagentPixel(pGC -> fgPixel);
+ mask |= GCForeground;
+
+ values.background = nxagentPixel(pGC -> bgPixel);
+ mask |= GCBackground;
+
+ values.line_width = pGC -> lineWidth;
+ mask |= GCLineWidth;
+
+ values.line_style = pGC -> lineStyle;
+ mask |= GCLineStyle;
+
+ values.cap_style = pGC -> capStyle;
+ mask |= GCCapStyle;
+
+ values.join_style = pGC -> joinStyle;
+ mask |= GCJoinStyle;
+
+ values.fill_style = pGC -> fillStyle;
+ mask |= GCFillStyle;
+
+ values.fill_rule = pGC -> fillRule;
+ mask |= GCFillRule;
+
+ values.arc_mode = pGC -> arcMode;
+ mask |= GCArcMode;
+
+ values.ts_x_origin = pGC -> patOrg.x;
+ mask |= GCTileStipXOrigin;
+
+ values.ts_y_origin = pGC -> patOrg.y;
+ mask |= GCTileStipYOrigin;
+
+ values.subwindow_mode = pGC -> subWindowMode;
+ mask |= GCSubwindowMode;
+
+ values.graphics_exposures = pGC -> graphicsExposures;
+ mask |= GCGraphicsExposures;
+
+ /*
+ * The GCClipMask is set to none inside
+ * the GetScratchGC() function.
+ */
+
+ values.clip_x_origin = pGC -> clipOrg.x;
+ mask |= GCClipXOrigin;
+
+ values.clip_y_origin = pGC -> clipOrg.y;
+ mask |= GCClipYOrigin;
+
+ XChangeGC(nxagentDisplay, nxagentGC(pGC), mask, &values);
+
+ memset(&(nxagentGCPriv(pGC) -> lastServerValues), 0, sizeof(XGCValues));
+
+ return pGC;
+}
+
+/*
+ * This function is only a wrapper for
+ * FreeScratchGC.
+ */
+void nxagentFreeScratchGC(GCPtr pGC)
+{
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFreeScratchGC: WARNING! pGC is NULL.\n");
+ #endif
+
+ return;
+ }
+
+ FreeScratchGC(pGC);
+}
+
+/*
+ * The GCs belonging to this list are used
+ * only in the synchronization put images,
+ * to be sure they preserve the default va-
+ * lues and to avoid XChangeGC() requests.
+ */
+
+GCPtr nxagentGetGraphicContext(DrawablePtr pDrawable)
+{
+ int i;
+ int result;
+
+ for (i = 0; i < nxagentGraphicContextsSize; i++)
+ {
+ if (pDrawable -> depth == nxagentGraphicContexts[i].depth)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetGraphicContext: Found a valid GC at [%p] for depth [%d].\n",
+ (void *) nxagentGraphicContexts[i].pGC, pDrawable -> depth);
+ #endif
+
+ /*
+ * Reconnect the GC if needed.
+ */
+
+ if (nxagentGraphicContexts[i].dirty == 1)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentGetGraphicContext: Going to reconnect the GC.\n");
+ #endif
+
+ result = 1;
+
+ nxagentReconnectGC(nxagentGraphicContexts[i].pGC, (XID) 0, &result);
+
+ if (result == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGetGraphicContext: WARNING! Failed to reconnect the GC.\n");
+ #endif
+
+ return NULL;
+ }
+
+ nxagentGraphicContexts[i].dirty = 0;
+ }
+
+ return nxagentGraphicContexts[i].pGC;
+ }
+ }
+
+ return nxagentCreateGraphicContext(pDrawable -> depth);
+}
+
+GCPtr nxagentCreateGraphicContext(int depth)
+{
+ GCPtr pGC;
+
+ nxagentGraphicContextsPtr nxagentGCs;
+
+ XID attributes[2];
+
+ /*
+ * We have not found a GC, so we have
+ * to spread the list and add a new GC.
+ */
+
+ nxagentGCs = realloc(nxagentGraphicContexts, (nxagentGraphicContextsSize + 1) * sizeof(nxagentGraphicContextsRec));
+
+ if (nxagentGCs == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateGraphicContext: Cannot allocate memory for a GC.\n");
+ #endif
+
+ return NULL;
+ }
+
+ nxagentGraphicContexts = nxagentGCs;
+
+ pGC = CreateScratchGC(nxagentDefaultScreen, depth);
+
+ if (pGC == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreateGraphicContext: Failed to create a GC for depth [%d].\n",
+ depth);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Color used in nxagentFillRemoteRegion().
+ */
+
+ attributes[0] = 0xc1c1c1;
+
+ if (depth == 15 || depth == 16)
+ {
+ Color32to16(attributes[0]);
+ }
+
+ /*
+ * The IncludeInferiors property is useful to
+ * solve problems when synchronizing windows
+ * covered by an invisible child.
+ */
+
+ attributes[1] = IncludeInferiors;
+
+ ChangeGC(pGC, GCForeground | GCSubwindowMode, attributes);
+
+ nxagentGraphicContexts[nxagentGraphicContextsSize].pGC = pGC;
+ nxagentGraphicContexts[nxagentGraphicContextsSize].depth = depth;
+ nxagentGraphicContexts[nxagentGraphicContextsSize].dirty = 0;
+
+ nxagentGraphicContextsSize++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreateGraphicContext: GC [%p] for depth [%d] added to the list of size [%d].\n",
+ (void *) pGC, depth, nxagentGraphicContextsSize);
+ #endif
+
+ return pGC;
+}
+
+/*
+ * This initialization is called in the InitOutput()
+ * function immediately after opening the screen,
+ * which is used to create the GCs.
+ */
+
+void nxagentAllocateGraphicContexts(void)
+{
+ int *depths;
+
+ int i;
+
+ depths = nxagentDepths;
+
+ for (i = 0; i < nxagentNumDepths; i++)
+ {
+ nxagentCreateGraphicContext(*depths);
+
+ depths++;
+ }
+}
+
+void nxagentDisconnectGraphicContexts(void)
+{
+ int i;
+
+ for (i = 0; i < nxagentGraphicContextsSize; i++)
+ {
+ nxagentGraphicContexts[i].dirty = 1;
+ }
+
+ return;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCOps.c b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c
new file mode 100644
index 000000000..1bca067fc
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.c
@@ -0,0 +1,2104 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "scrnintstr.h"
+#include "resource.h"
+#include "dixstruct.h"
+#include "../../fb/fb.h"
+
+#include "Agent.h"
+#include "Composite.h"
+#include "Display.h"
+#include "Visual.h"
+#include "Drawable.h"
+#include "Pixmaps.h"
+#include "GCs.h"
+#include "Image.h"
+#include "Font.h"
+#include "Events.h"
+#include "Client.h"
+#include "Trap.h"
+#include "Holder.h"
+#include "Args.h"
+#include "Screen.h"
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * Temporarily set/reset the trap.
+ */
+
+static int nxagentSaveGCTrap;
+
+#define SET_GC_TRAP() \
+{ \
+ nxagentSaveGCTrap = nxagentGCTrap;\
+\
+ nxagentGCTrap = 1; \
+}
+
+#define RESET_GC_TRAP() \
+{ \
+ nxagentGCTrap = nxagentSaveGCTrap; \
+}
+
+/*
+ * This is currently unused.
+ */
+
+RegionPtr nxagentBitBlitHelper(GC *pGC);
+
+/*
+ * The NX agent implementation of the
+ * X server's graphics functions.
+ */
+
+void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans,
+ xPoint *pPoints, int *pWidths, int fSorted)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to FillSpans on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbFillSpans(nxagentVirtualDrawable(pDrawable), pGC, nSpans, pPoints, pWidths, fSorted);
+ }
+ else
+ {
+ fbFillSpans(pDrawable, pGC, nSpans, pPoints, pWidths, fSorted);
+ }
+}
+
+void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc,
+ xPoint *pPoints, int *pWidths, int nSpans, int fSorted)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to SetSpans on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbSetSpans(nxagentVirtualDrawable(pDrawable), pGC, pSrc, pPoints, pWidths, nSpans, fSorted);
+ }
+ else
+ {
+ fbSetSpans(pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted);
+ }
+}
+
+void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints,
+ int *pWidths, int nSpans, char *pBuffer)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: going to GetSpans on FB pixmap [%p].\n",
+ (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbGetSpans(nxagentVirtualDrawable(pDrawable), maxWidth, pPoints, pWidths, nSpans, pBuffer);
+ }
+ else
+ {
+ fbGetSpans(pDrawable, maxWidth, pPoints, pWidths, nSpans, pBuffer);
+ }
+}
+
+void nxagentQueryBestSize(int class, unsigned short *pwidth,
+ unsigned short *pheight, ScreenPtr pScreen)
+{
+ unsigned width, test;
+
+ switch(class)
+ {
+ case CursorShape:
+ if (*pwidth > pScreen->width)
+ *pwidth = pScreen->width;
+ if (*pheight > pScreen->height)
+ *pheight = pScreen->height;
+ break;
+ case TileShape:
+ case StippleShape:
+ width = *pwidth;
+ if (!width) break;
+ /* Return the closes power of two not less than what they gave me */
+ test = 0x80000000;
+ /* Find the highest 1 bit in the width given */
+ while(!(test & width))
+ test >>= 1;
+ /* If their number is greater than that, bump up to the next
+ * power of two */
+ if((test - 1) & width)
+ test <<= 1;
+ *pwidth = test;
+ /* We don't care what height they use */
+ break;
+ }
+}
+
+RegionPtr nxagentBitBlitHelper(GC *pGC)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentBitBlitHelper: Called for GC at [%p].\n", (void *) pGC);
+ #endif
+
+ /*
+ * Force NullRegion. We consider enough the graphics
+ * expose events generated internally by the nxagent
+ * server.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBitBlitHelper: WARNING! Skipping check on exposures events.\n");
+ #endif
+
+ return NullRegion;
+}
+
+/*
+ * The deferring of X_RenderCompositeTrapezoids caused
+ * an ugly effect on pulldown menu: as the background
+ * may be not synchronized, the text floats in an invi-
+ * sible window. To avoid such effects, we use a system
+ * to guess if the destination target of a copy area
+ * is a popup, by assuming that those kind of windows
+ * use the override redirect property.
+ */
+
+int nxagentWindowIsPopup(DrawablePtr pDrawable)
+{
+ WindowPtr parent;
+
+ int windowIsPopup;
+ int level;
+
+ if (pDrawable -> type != DRAWABLE_WINDOW)
+ {
+ return 0;
+ }
+
+ windowIsPopup = 0;
+
+ if (((WindowPtr) pDrawable) -> overrideRedirect == 1)
+ {
+ windowIsPopup = 1;
+ }
+ else
+ {
+ parent = ((WindowPtr) pDrawable) -> parent;
+
+ /*
+ * Go up on the tree until a parent
+ * exists or 4 windows has been che-
+ * cked. This seems a good limit to
+ * up children's popup.
+ */
+
+ level = 0;
+
+ while (parent != NULL && ++level <= 4)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWindowIsPopup: Window [%p] has parent [%p] in tree with OverrideRedirect [%d] "
+ " Level [%d].\n", (void *) pDrawable, (void *) parent, parent -> overrideRedirect, level);
+ #endif
+
+ if (parent -> overrideRedirect == 1)
+ {
+ windowIsPopup = 1;
+
+ break;
+ }
+
+ parent = parent -> parent;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowIsPopup: Window [%p] %s to be a popup.\n", (void *) pDrawable,
+ windowIsPopup == 1 ? "seems" : "does not seem");
+ #endif
+
+ return windowIsPopup;
+}
+
+/*
+ * This function returns 1 if the
+ * XCopyArea request must be skipped.
+ */
+
+int nxagentDeferCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width,
+ int height, int dstx, int dsty)
+{
+ RegionPtr pSrcRegion;
+ RegionPtr pClipRegion, pCorruptedRegion;
+ RegionRec corruptedRegion, tmpRegion;
+
+ /*
+ * If the destination drawable is a popup
+ * window, we try to synchronize the source
+ * drawable to show a nice menu. Anyway if
+ * this synchronization breaks, the copy area
+ * is handled in the normal way.
+ */
+
+/*
+FIXME: The popup could be synchronized with one
+ single put image, clipped to the corrup-
+ ted region. As an intermediate step, the
+ pixmap to synchronize could be copied on
+ a cleared scratch pixmap, in order to
+ have a solid color in the clipped regions.
+*/
+
+ if (nxagentOption(DeferLevel) >= 2 &&
+ pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentPixmapContainTrapezoids((PixmapPtr) pSrcDrawable) == 1 &&
+ nxagentWindowIsPopup(pDstDrawable) == 1)
+ {
+ pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Copying to a popup menu. Source region [%d,%d,%d,%d].\n",
+ pSrcRegion -> extents.x1, pSrcRegion -> extents.y1,
+ pSrcRegion -> extents.x2, pSrcRegion -> extents.y2);
+ #endif
+
+ RegionInit(&corruptedRegion, NullBox, 1);
+
+ RegionIntersect(&corruptedRegion,
+ pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
+
+ if (RegionNil(&corruptedRegion) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n",
+ (void *) pSrcDrawable);
+ #endif
+
+ nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion, EVENT_BREAK, NULL);
+ }
+
+ RegionUninit(&corruptedRegion);
+
+ nxagentFreeRegion(pSrcDrawable, pSrcRegion);
+
+ if (nxagentDrawableStatus(pSrcDrawable) == Synchronized)
+ {
+ return 0;
+ }
+ }
+
+ /*
+ * We are going to decide if the source drawable
+ * must be synchronized before using it, or if
+ * the copy will be clipped to the synchronized
+ * source region.
+ */
+
+ if ((pDstDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentOption(DeferLevel) > 0) || nxagentOption(DeferLevel) >= 3)
+ {
+ pClipRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy,
+ width, height);
+
+ /*
+ * We called this variable pCorruptedRegion
+ * because in the worst case the corrupted
+ * region will be equal to the destination
+ * region. The GC's clip mask is used to
+ * narrow the destination.
+ */
+
+ pCorruptedRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty,
+ width, height);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Copy area source region is [%d,%d,%d,%d].\n",
+ pClipRegion -> extents.x1, pClipRegion -> extents.y1,
+ pClipRegion -> extents.x2, pClipRegion -> extents.y2);
+ #endif
+
+ RegionSubtract(pClipRegion, pClipRegion, nxagentCorruptedRegion(pSrcDrawable));
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Usable copy area source region is [%d,%d,%d,%d].\n",
+ pClipRegion -> extents.x1, pClipRegion -> extents.y1,
+ pClipRegion -> extents.x2, pClipRegion -> extents.y2);
+ #endif
+
+ if (pGC -> clientClip == NULL || pGC -> clientClipType != CT_REGION)
+ {
+ #ifdef WARNING
+
+ if (pGC -> clientClipType != CT_NONE)
+ {
+ fprintf(stderr, "nxagentDeferCopyArea: WARNING! pGC [%p] has a clip type [%d].\n",
+ (void *) pGC, pGC -> clientClipType);
+ }
+
+ #endif
+
+ RegionTranslate(pClipRegion, dstx - srcx, dsty - srcy);
+ }
+ else
+ {
+ RegionInit(&tmpRegion, NullBox, 1);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Going to modify the original GC [%p] with clip mask "
+ "[%d,%d,%d,%d] and origin [%d,%d].\n",
+ (void *) pGC,
+ ((RegionPtr) pGC -> clientClip) -> extents.x1, ((RegionPtr) pGC -> clientClip) -> extents.y1,
+ ((RegionPtr) pGC -> clientClip) -> extents.x2, ((RegionPtr) pGC -> clientClip) -> extents.y2,
+ pGC -> clipOrg.x, pGC -> clipOrg.y);
+ #endif
+
+ RegionCopy(&tmpRegion, (RegionPtr) pGC -> clientClip);
+
+ if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0)
+ {
+ RegionTranslate(&tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y);
+ }
+
+ RegionTranslate(pClipRegion, dstx - srcx, dsty - srcy);
+
+ RegionIntersect(pClipRegion, &tmpRegion, pClipRegion);
+
+ RegionUninit(&tmpRegion);
+ }
+
+ /*
+ * The corrupted region on the destination
+ * drawable is composed by the areas of the
+ * destination that we are not going to copy.
+ */
+
+ RegionSubtract(pCorruptedRegion, pCorruptedRegion, pClipRegion);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Recomputed clip region is [%d,%d,%d,%d][%ld].\n",
+ pClipRegion -> extents.x1, pClipRegion -> extents.y1,
+ pClipRegion -> extents.x2, pClipRegion -> extents.y2,
+ RegionNumRects(pClipRegion));
+
+ fprintf(stderr, "nxagentDeferCopyArea: Inherited corrupted region is [%d,%d,%d,%d][%ld].\n",
+ pCorruptedRegion -> extents.x1, pCorruptedRegion -> extents.y1,
+ pCorruptedRegion -> extents.x2, pCorruptedRegion -> extents.y2,
+ RegionNumRects(pCorruptedRegion));
+ #endif
+
+ /*
+ * The destination drawable inherits both the
+ * synchronized and the corrupted region.
+ */
+
+ if (RegionNil(pClipRegion) == 0)
+ {
+ nxagentUnmarkCorruptedRegion(pDstDrawable, pClipRegion);
+ }
+
+ if (RegionNil(pCorruptedRegion) == 0)
+ {
+ nxagentMarkCorruptedRegion(pDstDrawable, pCorruptedRegion);
+ }
+
+ if (RegionNil(pClipRegion) == 0)
+ {
+ GCPtr targetGC;
+
+ CARD32 targetAttributes[2];
+
+ Bool pClipRegionFree = True;
+
+ /*
+ * As we want to copy only the synchronized
+ * areas of the source drawable, we create
+ * a new GC copying the original one and
+ * setting a new clip mask.
+ */
+
+ targetGC = GetScratchGC(pDstDrawable -> depth, pDstDrawable -> pScreen);
+
+ ValidateGC(pDstDrawable, targetGC);
+
+ CopyGC(pGC, targetGC, GCFunction | GCPlaneMask | GCSubwindowMode |
+ GCClipXOrigin | GCClipYOrigin | GCClipMask | GCForeground |
+ GCBackground | GCGraphicsExposures);
+
+ if (RegionNumRects(pClipRegion) == 1)
+ {
+ /*
+ * If the region to copy is formed by one
+ * rectangle, we change only the copy coor-
+ * dinates.
+ */
+
+ srcx = srcx + pClipRegion -> extents.x1 - dstx;
+ srcy = srcy + pClipRegion -> extents.y1 - dsty;
+
+ dstx = pClipRegion -> extents.x1;
+ dsty = pClipRegion -> extents.y1;
+
+ width = pClipRegion -> extents.x2 - pClipRegion -> extents.x1;
+ height = pClipRegion -> extents.y2 - pClipRegion -> extents.y1;
+ }
+ else
+ {
+ /*
+ * Setting the clip mask origin. This
+ * operation must precede the clip chan-
+ * ge, because the origin information is
+ * used in the XSetClipRectangles().
+ */
+
+ targetAttributes[0] = 0;
+ targetAttributes[1] = 0;
+
+ ChangeGC(targetGC, GCClipXOrigin | GCClipYOrigin, targetAttributes);
+
+ /*
+ * Setting the new clip mask.
+ */
+
+ nxagentChangeClip(targetGC, CT_REGION, pClipRegion, 0);
+
+ /*
+ * Next call to nxagentChangeClip() will destroy
+ * pClipRegion, so it has not to be freed.
+ */
+
+ pClipRegionFree = False;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Going to execute a copy area with clip mask "
+ "[%d,%d,%d,%d] and origin [%d,%d].\n", ((RegionPtr) targetGC -> clientClip) -> extents.x1,
+ ((RegionPtr) targetGC -> clientClip) -> extents.y1,
+ ((RegionPtr) targetGC -> clientClip) -> extents.x2,
+ ((RegionPtr) targetGC -> clientClip) -> extents.y2,
+ targetGC -> clipOrg.x, targetGC -> clipOrg.y);
+ #endif
+ }
+
+ XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
+ nxagentGC(targetGC), srcx, srcy, width, height, dstx, dsty);
+
+ nxagentChangeClip(targetGC, CT_NONE, NullRegion, 0);
+
+ if (pClipRegionFree == True)
+ {
+ nxagentFreeRegion(pSrcDrawable, pClipRegion);
+ }
+
+ FreeScratchGC(targetGC);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDeferCopyArea: The clipped region is NIL. CopyArea skipped.\n");
+ #endif
+
+ /*
+ * The pClipRegion is destroyed calling nxagentChangeClip(),
+ * so we deallocate it explicitly only if we don't change
+ * the clip.
+ */
+
+ nxagentFreeRegion(pSrcDrawable, pClipRegion);
+ }
+
+ nxagentFreeRegion(pSrcDrawable, pCorruptedRegion);
+
+ return 1;
+ }
+ else
+ {
+ pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDeferCopyArea: Source region [%d,%d,%d,%d].\n",
+ pSrcRegion -> extents.x1, pSrcRegion -> extents.y1,
+ pSrcRegion -> extents.x2, pSrcRegion -> extents.y2);
+ #endif
+
+ RegionInit(&corruptedRegion, NullBox, 1);
+
+ RegionIntersect(&corruptedRegion,
+ pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
+
+ if (RegionNil(&corruptedRegion) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n",
+ (void *) pSrcDrawable);
+ #endif
+
+ nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL);
+ }
+
+ RegionUninit(&corruptedRegion);
+
+ nxagentFreeRegion(pSrcDrawable, pSrcRegion);
+ }
+
+ return 0;
+}
+
+RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width,
+ int height, int dstx, int dsty)
+{
+ int leftPad = 0;
+ unsigned int format;
+ unsigned long planeMask = 0xffffffff;
+
+ RegionPtr pDstRegion;
+
+ int skip = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n",
+ (pSrcDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
+ (pDstDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
+ (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
+ #endif
+
+ /*
+ * Here, before using fbDoCopy() called by fbCopyArea(),
+ * it should be provided that the cast in fbDoCopy() from
+ * int to short int would not cut off significative bits.
+ */
+
+ if (dstx + pDstDrawable->x + width > 32767)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: x2 exceeding short int.\n");
+ #endif
+
+ width = 32767 - dstx - pDstDrawable->x;
+
+ if (width <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on x2 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ if (dstx + pDstDrawable->x < -32768)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: x1 exceeding short int.\n");
+ #endif
+
+ width += pDstDrawable->x + dstx + 32768;
+ srcx -= pDstDrawable->x + dstx + 32768;
+ dstx = -32768 - pDstDrawable->x;
+
+ if (width <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on x1 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ if (dsty + pDstDrawable->y + height > 32767)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: y2 exceeding short int.\n");
+ #endif
+
+ height = 32767 - dsty - pDstDrawable->y;
+
+ if (height <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on y2 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+ if (dsty + pDstDrawable->y < -32768)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: y1 exceeding short int.\n");
+ #endif
+
+ height += 32768 + pDstDrawable->y + dsty;
+ srcy -= 32768 + pDstDrawable->y + dsty;
+ dsty = -32768 - pDstDrawable->y;
+
+ if (height <= 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Returning null on y1 check.\n");
+ #endif
+
+ return NullRegion;
+ }
+ }
+
+
+ if (nxagentGCTrap == 1 || nxagentShmTrap == 1)
+ {
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable),
+ nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ else
+ {
+ return fbCopyArea(pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+
+ return NullRegion;
+ }
+
+ /*
+ * Try to detect if the copy area is to a window
+ * that is unmapped or fully covered. Similarly
+ * to the check in Image.c, this is of little use.
+ */
+
+ if (nxagentOption(IgnoreVisibility) == 0 && pDstDrawable -> type == DRAWABLE_WINDOW &&
+ (nxagentWindowIsVisible((WindowPtr) pDstDrawable) == 0 ||
+ (nxagentDefaultWindowIsVisible() == 0 && nxagentCompositeEnable == 0)))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Prevented operation on fully obscured window at [%p].\n",
+ (void *) pDstDrawable);
+ #endif
+
+ return NullRegion;
+ }
+
+ /*
+ * If the pixmap is on shared memory, we can't
+ * know if the pixmap content is changed and
+ * so have to translate the operation in a put
+ * image operation. This can seriously affect
+ * the performance.
+ */
+
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pSrcDrawable))
+ {
+ char *data;
+ int depth, length;
+
+ depth = pSrcDrawable -> depth;
+
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ length = nxagentImageLength(width, height, format, leftPad, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCopyArea: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ return NullRegion;
+ }
+
+ fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data);
+
+ /*
+ * If the source is a shared memory pixmap,
+ * put the image directly to the destination.
+ */
+
+ nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty,
+ width, height, leftPad, format, data);
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentCopyArea: Realize Pixmap %p virtual %p x %d y %d w %d h %d\n",
+ (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable),
+ srcx, srcy, width, height);
+ #endif
+
+ free(data);
+
+ /*
+ * If the source is a shared memory pixmap, the
+ * content of the framebuffer has been placed
+ * directly on the destination so we can skip
+ * the copy area operation.
+ */
+
+ skip = 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] sx %d sy %d dx %d dy %d size w %d h %d\n",
+ ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
+ ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
+ (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
+ #endif
+
+ if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized)
+ {
+ skip = nxagentDeferCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
+ width, height, dstx, dsty);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentCopyArea: Source drawable at [%p] already synchronized.\n",
+ (void *) pSrcDrawable);
+ }
+ #endif
+
+ if (skip == 0)
+ {
+ XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
+ nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty);
+
+ /*
+ * The copy area restored the synchroni-
+ * zation status of destination drawable.
+ */
+
+ if (nxagentDrawableStatus(pDstDrawable) == NotSynchronized)
+ {
+ pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
+
+ nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDstDrawable, pDstRegion);
+ }
+ }
+
+ if (nxagentDrawableContainGlyphs(pSrcDrawable) == 1)
+ {
+ nxagentSetDrawableContainGlyphs(pDstDrawable, 1);
+ }
+
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrcDrawable);
+ }
+
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to [%p]\n",
+ (void *) nxagentVirtualDrawable(pSrcDrawable),
+ (void *) nxagentVirtualDrawable(pDstDrawable));
+ #endif
+
+ return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable),
+ nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to window [%p]\n",
+ (void *) nxagentVirtualDrawable(pSrcDrawable),
+ (void *) pDstDrawable);
+ #endif
+
+ return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ /*
+ * If we are here the source drawable
+ * must be a window.
+ */
+
+ if (((WindowPtr) pSrcDrawable) -> viewable)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to virtual pixmap [%p]\n",
+ (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pDstDrawable));
+ #endif
+
+ return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ }
+ else
+ {
+ /*
+ * If we are here the source drawable
+ * must be a window.
+ */
+
+ if (((WindowPtr) pSrcDrawable) -> viewable)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to window [%p]\n",
+ (void *) pSrcDrawable, (void *) pDstDrawable);
+ #endif
+
+ return fbCopyArea(pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty);
+ }
+ }
+
+ return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty, 0);
+}
+
+RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long plane)
+{
+ unsigned int format;
+ int leftPad = 0;
+ unsigned long planeMask = 0xffffffff;
+
+ RegionPtr pSrcRegion, pDstRegion;
+ RegionRec corruptedRegion;
+
+ int skip = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyPlane: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n",
+ ((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
+ ((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
+ (void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
+ #endif
+
+ if (nxagentGCTrap == 1 || nxagentShmTrap == 1)
+ {
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable),
+ nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else
+ {
+ return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
+ dstx, dsty, plane);
+ }
+
+ return NullRegion;
+ }
+
+ /*
+ * If the pixmap is on shared memory, we can't
+ * know if the pixmap content is changed and
+ * so have to translate the operation in a put
+ * image operation. This can seriously affect
+ * the performance.
+ */
+
+ if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pSrcDrawable))
+ {
+ char *data;
+ int depth, length;
+
+ depth = pSrcDrawable -> depth;
+
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ length = nxagentImageLength(width, height, format, leftPad, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCopyPlane: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ return 0;
+ }
+
+ fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data);
+
+ /*
+ * If the source is a shared memory pixmap,
+ * put the image directly to the destination.
+ */
+
+ nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty,
+ width, height, leftPad, format, data);
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentCopyPlane: Synchronize Pixmap %p virtual %p x %d y %d w %d h %d \n",
+ (void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable),
+ srcx, srcy, width, height);
+ #endif
+
+ free(data);
+
+ /*
+ * If the source is a shared memory pixmap, the
+ * content of the framebuffer has been placed
+ * directly on the destination so we can skip
+ * the copy plane operation.
+ */
+
+ skip = 1;
+ }
+
+ if (skip == 0 && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized)
+ {
+ if (pDstDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentOption(DeferLevel) > 0)
+ {
+ pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
+
+ nxagentMarkCorruptedRegion(pDstDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDstDrawable, pDstRegion);
+
+ skip = 1;
+ }
+ else
+ {
+ pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
+
+ RegionInit(&corruptedRegion, NullBox, 1);
+
+ RegionIntersect(&corruptedRegion,
+ pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
+
+ if (RegionNil(&corruptedRegion) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyPlane: Forcing the synchronization of source drawable at [%p].\n",
+ (void *) pSrcDrawable);
+ #endif
+
+ nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL);
+
+ pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
+
+ nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDstDrawable, pDstRegion);
+ }
+
+ RegionUninit(&corruptedRegion);
+
+ nxagentFreeRegion(pSrcDrawable, pSrcRegion);
+ }
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentCopyPlane: Source drawable at [%p] already synchronized.\n",
+ (void *) pSrcDrawable);
+ }
+ #endif
+
+ if (skip == 0)
+ {
+ XCopyPlane(nxagentDisplay,
+ nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
+ nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty, plane);
+ }
+
+ if ((pSrcDrawable)->type == DRAWABLE_PIXMAP &&
+ (pDstDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCopyPlane: going to copy plane from FB pixmap [%p] to [%p].\n",
+ (void *) nxagentVirtualDrawable(pSrcDrawable),
+ (void *) nxagentVirtualDrawable(pDstDrawable));
+ #endif
+
+ return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable),
+ nxagentVirtualDrawable(pDstDrawable),
+ pGC, srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), pGC,
+ srcx, srcy, width, height, dstx, dsty, plane);
+ }
+ else
+ {
+ return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty, plane);
+ }
+
+ return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty, plane);
+}
+
+void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int nPoints, xPoint *pPoints)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentPolyPoint: Drawable at [%p] GC at [%p] Points [%d].\n",
+ (void *) pDrawable, (void *) pGC, nPoints);
+ #endif
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
+ }
+ else
+ {
+ fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly point on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly point enters with virtual pixmap [%p] parent is [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawPoints(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode);
+ }
+ }
+ else
+ {
+ XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, mode);
+ }
+
+ fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
+
+ return;
+ }
+ else
+ {
+ XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, mode);
+
+ fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints);
+ }
+}
+
+void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int nPoints, xPoint *pPoints)
+{
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
+ }
+ else
+ {
+ fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly line on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly lines enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawLines(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode);
+ }
+ }
+ else
+ {
+ XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, mode);
+ }
+
+ fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
+
+ return;
+ }
+ else
+ {
+ XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, mode);
+
+ fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints);
+ }
+}
+
+void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC,
+ int nSegments, xSegment *pSegments)
+{
+ #ifdef TEST
+
+ if (nSegments == 1)
+ {
+ fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segment [%d,%d,%d,%d].\n",
+ (void *) pDrawable, (void *) pGC,
+ pSegments -> x1, pSegments -> y1, pSegments -> x2, pSegments -> y2);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segments [%d].\n",
+ (void *) pDrawable, (void *) pGC, nSegments);
+ }
+
+ #endif
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments);
+ }
+ else
+ {
+ fbPolySegment(pDrawable, pGC, nSegments, pSegments);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly segment on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly segment enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawSegments(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XSegment *) pSegments, nSegments);
+ }
+ }
+ else
+ {
+ XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XSegment *) pSegments, nSegments);
+ }
+
+ SET_GC_TRAP();
+ fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments);
+ RESET_GC_TRAP();
+
+ return;
+ }
+ else
+ {
+ XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XSegment *) pSegments, nSegments);
+
+ SET_GC_TRAP();
+ fbPolySegment(pDrawable, pGC, nSegments, pSegments);
+ RESET_GC_TRAP();
+ }
+}
+
+void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
+ int nRectangles, xRectangle *pRectangles)
+{
+ #ifdef TEST
+
+ if (nRectangles == 1)
+ {
+ fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangle [%d,%d][%d,%d].\n",
+ (void *) pDrawable, (void *) pGC,
+ pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangles [%d].\n",
+ (void *) pDrawable, (void *) pGC, nRectangles);
+ }
+
+ #endif
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
+ }
+ else
+ {
+ miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly rectangle on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly rectangle enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles);
+ }
+ }
+ else
+ {
+ XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XRectangle *) pRectangles, nRectangles);
+ }
+
+ SET_GC_TRAP();
+
+ miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
+
+ RESET_GC_TRAP();
+
+ return;
+ }
+ else
+ {
+ XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XRectangle *) pRectangles, nRectangles);
+
+ SET_GC_TRAP();
+
+ miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles);
+
+ RESET_GC_TRAP();
+ }
+}
+
+void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC,
+ int nArcs, xArc *pArcs)
+{
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
+ }
+ else
+ {
+ fbPolyArc(pDrawable, pGC, nArcs, pArcs);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly arc on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly arc enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XArc *) pArcs, nArcs);
+ }
+ }
+ else
+ {
+ XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XArc *) pArcs, nArcs);
+ }
+
+ fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
+
+ return;
+ }
+ else
+ {
+ XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XArc *) pArcs, nArcs);
+
+ fbPolyArc(pDrawable, pGC, nArcs, pArcs);
+ }
+}
+
+void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int nPoints, xPoint *pPoints)
+{
+ xPoint *newPoints = NULL;
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints);
+ }
+ else
+ {
+ miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints);
+ }
+
+ return;
+ }
+
+ /*
+ * The coordinate-mode must be CoordModePrevious
+ * to make better use of differential encoding of
+ * X_FillPoly request by the side of proxy.
+ */
+
+ if (mode == CoordModeOrigin)
+ {
+ int i;
+
+ mode = CoordModePrevious;
+
+ newPoints = malloc(nPoints * sizeof(xPoint));
+
+ /*
+ * The first point is always relative
+ * to the drawable's origin.
+ */
+
+ newPoints[0].x = pPoints[0].x;
+ newPoints[0].y = pPoints[0].y;
+
+ /*
+ * If coordinate-mode is CoordModePrevious,
+ * the points following the first are rela-
+ * tive to the previous point.
+ */
+
+ for (i = 1; i < nPoints; i++)
+ {
+ newPoints[i].x = pPoints[i].x - pPoints[i-1].x;
+ newPoints[i].y = pPoints[i].y - pPoints[i-1].y;
+ }
+
+ pPoints = newPoints;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to fill polygon on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: fill polygon enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XFillPolygon(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XPoint *) pPoints, nPoints, shape, mode);
+ }
+ }
+ else
+ {
+ XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, shape, mode);
+ }
+
+ SET_GC_TRAP();
+
+ miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints);
+
+ RESET_GC_TRAP();
+ }
+ else
+ {
+ XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XPoint *) pPoints, nPoints, shape, mode);
+
+ SET_GC_TRAP();
+
+ miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints);
+
+ RESET_GC_TRAP();
+ }
+
+ if (newPoints != NULL)
+ {
+ free(newPoints);
+ }
+}
+
+void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
+ int nRectangles, xRectangle *pRectangles)
+{
+ RegionPtr rectRegion;
+
+ int inheritCorruptedRegion;
+
+ #ifdef TEST
+
+ if (nRectangles == 1)
+ {
+ fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangle [%d,%d][%d,%d].\n",
+ (void *) pDrawable, (void *) pGC, pGC -> fillStyle,
+ pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangles [%d].\n",
+ (void *) pDrawable, (void *) pGC, pGC -> fillStyle, nRectangles);
+ }
+
+ #endif
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
+ }
+ else
+ {
+ fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles);
+ }
+
+ return;
+ }
+
+ /*
+ * The PolyFillRect acts in two ways: if the GC
+ * has a corrupted tile, the operation propagates
+ * the corrupted region on the destination. In
+ * other cases, because the PolyFillRect will
+ * cover the destination, any corrupted region
+ * intersecting the target will be cleared.
+ */
+
+ inheritCorruptedRegion = 0;
+
+ if (pGC -> fillStyle == FillTiled &&
+ pGC -> tileIsPixel == 0 && pGC -> tile.pixmap != NULL)
+ {
+ nxagentIncreasePixmapUsageCounter(pGC -> tile.pixmap);
+
+ if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPolyFillRect: GC at [%p] uses corrupted tile pixmap at [%p]. Going to "
+ "corrupt the destination [%s][%p].\n", (void *) pGC, (void *) pGC -> tile.pixmap,
+ (pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDrawable);
+
+ #endif
+
+ inheritCorruptedRegion = 1;
+ }
+ }
+
+ if (inheritCorruptedRegion == 1 || nxagentDrawableStatus(pDrawable) == NotSynchronized)
+ {
+ rectRegion = RegionFromRects(nRectangles, pRectangles, CT_REGION);
+
+ if (pGC -> clientClip != NULL)
+ {
+ RegionRec tmpRegion;
+
+ RegionInit(&tmpRegion, NullBox, 1);
+
+ RegionCopy(&tmpRegion, ((RegionPtr) pGC -> clientClip));
+
+ if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0)
+ {
+ RegionTranslate(&tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y);
+ }
+
+ RegionIntersect(rectRegion, rectRegion, &tmpRegion);
+
+ RegionUninit(&tmpRegion);
+ }
+
+ if (inheritCorruptedRegion == 1)
+ {
+ /*
+ * The fill style should affect the cor-
+ * rupted region propagation: if the tile
+ * is not completely corrupted the region
+ * should be 'tiled' over the destination.
+ */
+
+ nxagentMarkCorruptedRegion(pDrawable, rectRegion);
+ }
+ else
+ {
+ if (pGC -> fillStyle != FillStippled && pGC -> fillStyle != FillOpaqueStippled)
+ {
+ nxagentUnmarkCorruptedRegion(pDrawable, rectRegion);
+ }
+ else
+ {
+ /*
+ * The stipple mask computation could cause
+ * an high fragmentation of the destination
+ * region. An analysis should be done to exa-
+ * mine the better solution (e.g.rdesktop
+ * uses stipples to draw texts).
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPolyFillRect: Synchronizing the region [%d,%d,%d,%d] before using "
+ "the stipple at [%p].\n", rectRegion -> extents.x1, rectRegion -> extents.y1,
+ rectRegion -> extents.x2, rectRegion -> extents.y2, (void *) pGC -> stipple);
+ #endif
+
+ nxagentSynchronizeRegion(pDrawable, rectRegion, NEVER_BREAK, NULL);
+ }
+ }
+
+ RegionDestroy(rectRegion);
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly fill rect on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly fill rect enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XFillRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles);
+ }
+ }
+ else
+ {
+ XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XRectangle *) pRectangles, nRectangles);
+ }
+
+ fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
+
+ return;
+ }
+ else
+ {
+ XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XRectangle *) pRectangles, nRectangles);
+
+ fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles);
+ }
+}
+
+void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
+ int nArcs, xArc *pArcs)
+{
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
+ }
+ else
+ {
+ miPolyFillArc(pDrawable, pGC, nArcs, pArcs);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly fillarc on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly fill arc enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XFillArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), (XArc *) pArcs, nArcs);
+ }
+ }
+ else
+ {
+ XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ (XArc *) pArcs, nArcs);
+ }
+
+ SET_GC_TRAP();
+
+ miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
+
+ RESET_GC_TRAP();
+
+ return;
+ }
+ else
+ {
+ XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), (XArc *) pArcs, nArcs);
+
+ SET_GC_TRAP();
+
+ miPolyFillArc(pDrawable, pGC, nArcs, pArcs);
+
+ RESET_GC_TRAP();
+ }
+}
+
+int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, char *string)
+{
+ int width;
+
+ /*
+ * While the session is suspended
+ * the font structure is NULL.
+ */
+
+ if (nxagentFontStruct(pGC -> font) == NULL)
+ {
+ return x;
+ }
+
+ width = XTextWidth(nxagentFontStruct(pGC->font), string, count);
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+ }
+ else
+ {
+ miPolyText8(pDrawable, pGC, x, y, count, string);
+ }
+
+ return width + x;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly text8 on FB pixmap [%p] with string [%s].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly text8 enters with virtual pixmap [%p] parent is [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), x, y, string, count);
+ }
+ }
+ else
+ {
+ XDrawString(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, string, count);
+ }
+
+ miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+
+ return width + x;
+ }
+ else
+ {
+ XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
+ x, y, string, count);
+
+ miPolyText8(pDrawable, pGC, x, y, count, string);
+ }
+
+ return width + x;
+}
+
+int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, unsigned short *string)
+{
+ int width;
+
+ /*
+ * While the session is suspended
+ * the font structure is NULL.
+ */
+
+ if (nxagentFontStruct(pGC -> font) == NULL)
+ {
+ return x;
+ }
+
+ width = XTextWidth16(nxagentFontStruct(pGC->font), (XChar2b *)string, count);
+
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+ }
+ else
+ {
+ miPolyText16(pDrawable, pGC, x, y, count, string);
+ }
+
+ return width + x;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to poly text16 on FB pixmap %p] with string [%s]\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly text16 enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+ }
+ }
+ else
+ {
+ XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+ }
+
+ miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+
+ return width + x;
+ }
+ else
+ {
+ XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+
+ miPolyText16(pDrawable, pGC, x, y, count, string);
+ }
+
+ return width + x;
+}
+
+void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, char *string)
+{
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+ }
+ else
+ {
+ miImageText8(pDrawable, pGC, x, y, count, string);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to image text8 on FB pixmap [%p] with string [%s].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), string);
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly image text8 enters with virtual pixmap [%p] parent is [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawImageString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), x, y, string, count);
+ }
+ }
+ else
+ {
+ XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, string, count);
+ }
+
+ miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+
+ return;
+ }
+ else
+ {
+ XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, string, count);
+
+ miImageText8(pDrawable, pGC, x, y, count, string);
+ }
+}
+
+void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, unsigned short *string)
+{
+ if (nxagentGCTrap == 1)
+ {
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+ }
+ else
+ {
+ miImageText16(pDrawable, pGC, x, y, count, string);
+ }
+
+ return;
+ }
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to image text16 on FB pixmap [%p] with string [%s].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
+ #endif
+
+ if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: poly image text16 enters with virtual pixmap = [%p] parent is = [%p]\n",
+ (void *) nxagentVirtualDrawable(pDrawable),
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ if (nxagentRealPixmap((PixmapPtr) pDrawable))
+ {
+ XDrawImageString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+ }
+ }
+ else
+ {
+ XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+ }
+
+ miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
+
+ return;
+ }
+ else
+ {
+ XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), x, y, (XChar2b *)string, count);
+
+ miImageText16(pDrawable, pGC, x, y, count, string);
+ }
+}
+
+void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nGlyphs, CharInfoPtr *pCharInfo,
+ void * pGlyphBase)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to imageGlyphBlt on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbImageGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
+ }
+ else
+ {
+ fbImageGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
+ }
+}
+
+void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nGlyphs, CharInfoPtr *pCharInfo,
+ void * pGlyphBase)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to PolyGlyphBlt on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbPolyGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
+ }
+ else
+ {
+ fbPolyGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
+ }
+}
+
+void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable,
+ int width, int height, int x, int y)
+{
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "GCOps: GC [%p] going to PushPixels on FB pixmap [%p].\n",
+ (void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap),
+ (DrawablePtr) nxagentVirtualDrawable(pDrawable),
+ width, height, x, y);
+ }
+ else
+ {
+ fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap),
+ (DrawablePtr) pDrawable, width, height, x, y);
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCOps.h b/nx-X11/programs/Xserver/hw/nxagent/GCOps.h
new file mode 100644
index 000000000..bbf7fa3df
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCOps.h
@@ -0,0 +1,113 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __GCOps_H__
+#define __GCOps_H__
+
+/*
+ * Graphic operations.
+ */
+
+void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans,
+ xPoint *pPoints, int *pWidths, int fSorted);
+
+void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc,
+ xPoint *pPoints, int *pWidths, int nSpans, int fSorted);
+
+void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints,
+ int *pWidths, int nSpans, char *pBuffer);
+
+RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width,
+ int height, int dstx, int dsty);
+
+RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty, unsigned long plane);
+
+void nxagentQueryBestSize(int class, unsigned short *pwidth,
+ unsigned short *pheight, ScreenPtr pScreen);
+
+void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int nPoints, xPoint *pPoints);
+
+void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int nPoints, xPoint *pPoints);
+
+void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC,
+ int nSegments, xSegment *pSegments);
+
+void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
+ int nRectangles, xRectangle *pRectangles);
+
+void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC,
+ int nArcs, xArc *pArcs);
+
+void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int nPoints, xPoint *pPoints);
+
+void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
+ int nRectangles, xRectangle *pRectangles);
+
+void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
+ int nArcs, xArc *pArcs);
+
+int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, char *string);
+
+int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, unsigned short *string);
+
+void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, char *string);
+
+void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, int count, unsigned short *string);
+
+void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nGlyphs, CharInfoPtr *pCharInfo, void * pGlyphBase);
+
+void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ unsigned int nGlyphs, CharInfoPtr *pCharInfo, void * pGlyphBase);
+
+void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable,
+ int width, int height, int x, int y);
+
+#endif /* __GCOps_H__ */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/GCs.h b/nx-X11/programs/Xserver/hw/nxagent/GCs.h
new file mode 100644
index 000000000..84b0063ab
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/GCs.h
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __GC_H__
+#define __GC_H__
+
+extern RESTYPE RT_NX_GC;
+
+/* This file uses the GC definition form Xlib.h as XlibGC. */
+
+typedef struct {
+ XlibGC gc;
+
+ int nClipRects;
+
+ XGCValues lastServerValues;
+
+ XID mid;
+
+ PixmapPtr pPixmap;
+
+} nxagentPrivGC;
+
+extern int nxagentGCPrivateIndex;
+
+typedef struct _nxagentGraphicContextsRec
+{
+ int depth;
+ GCPtr pGC;
+ int dirty;
+
+} nxagentGraphicContextsRec;
+
+typedef nxagentGraphicContextsRec *nxagentGraphicContextsPtr;
+extern nxagentGraphicContextsPtr nxagentGraphicContexts;
+extern int nxagentGraphicContextsSize;
+
+#define nxagentGCPriv(pGC) \
+ ((nxagentPrivGC *)((pGC) -> devPrivates[nxagentGCPrivateIndex].ptr))
+
+#define nxagentGC(pGC) (nxagentGCPriv(pGC) -> gc)
+
+#define nxagentCopyGCPriv(valueMask, valueField, src, mask, dst) \
+\
+ if (mask & valueMask) \
+ { \
+ nxagentGCPriv(dst) -> lastServerValues.valueField = \
+ nxagentGCPriv(src) -> lastServerValues.valueField; \
+ }
+
+#define nxagentTestGC(newValue, pvalue) \
+\
+ ((nxagentGCPriv(pGC) -> lastServerValues.pvalue == newValue) ? 0 : 1); \
+\
+ nxagentGCPriv(pGC) -> lastServerValues.pvalue = newValue
+
+Bool nxagentCreateGC(GCPtr pGC);
+void nxagentValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable);
+void nxagentChangeGC(GCPtr pGC, unsigned long mask);
+void nxagentCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+void nxagentDestroyGC(GCPtr pGC);
+void nxagentChangeClip(GCPtr pGC, int type, void * pValue, int nRects);
+void nxagentDestroyClip(GCPtr pGC);
+void nxagentDestroyClipHelper(GCPtr pGC);
+void nxagentCopyClip(GCPtr pGCDst, GCPtr pGCSrc);
+
+void nxagentDisconnectGC(void * p0, XID x1, void * p2);
+Bool nxagentDisconnectAllGCs(void);
+
+Bool nxagentReconnectAllGCs(void *p0);
+
+int nxagentDestroyNewGCResourceType(void * p, XID id);
+
+void nxagentFreeGCList(void);
+void nxagentInitGCSafeVector(void);
+
+GCPtr nxagentGetScratchGC(unsigned depth, ScreenPtr pScreen);
+void nxagentFreeScratchGC(GCPtr pGC);
+
+GCPtr nxagentGetGraphicContext(DrawablePtr pDrawable);
+void nxagentAllocateGraphicContexts(void);
+
+#endif /* __GC_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Handlers.c b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c
new file mode 100644
index 000000000..634f7aafd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.c
@@ -0,0 +1,1325 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "dixstruct.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "osdep.h"
+
+#include "Agent.h"
+#include "Handlers.h"
+#include "Display.h"
+#include "Events.h"
+#include "Client.h"
+#include "Reconnect.h"
+#include "Dialog.h"
+#include "Drawable.h"
+#include "Splash.h"
+#include "Screen.h"
+#include "Millis.h"
+
+#define Window XlibWindow
+#include "compext/Compext.h"
+#undef Window
+
+#include <nx/Shadow.h>
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * Log begin and end of the important
+ * handlers.
+ */
+
+#undef BLOCKS
+
+/*
+ * If not defined, flush immediately
+ * upon entering the block handler.
+ */
+
+#define FLUSH_AFTER_MULTIPLE_READS
+
+/*
+ * The soft limit should roughly match
+ * the size of the Xlib I/O buffer.
+ */
+
+#define BYTES_BEFORE_SOFT_TOKEN 2048
+#define BYTES_BEFORE_HARD_TOKEN 65536
+
+/*
+ * Maximum number of synchronization
+ * requests before waiting for the
+ * remote.
+ */
+
+#define TOKENS_PENDING_LIMIT 8
+
+/*
+ * Limits are very unobtrusive. We don't
+ * want to interfere with the normal
+ * dispatching.
+ */
+
+#define BYTES_BEFORE_YIELD 1048576
+#define TIME_BEFORE_YIELD 500
+
+/*
+ * Dinamically reduce the display buffer
+ * size after a congestion.
+ */
+
+#undef DYNAMIC_DISPLAY_BUFFER
+
+/*
+ * Minimum display buffer size.
+ */
+
+#define MINIMUM_DISPLAY_BUFFER 512
+
+#ifdef NX_DEBUG_INPUT
+extern int nxagentDebugInputDevices;
+extern unsigned long nxagentLastInputDevicesDumpTime;
+
+extern void nxagentDumpInputDevicesState(void);
+#endif
+
+/*
+ * Used in the handling of the X desktop
+ * manager protocol.
+ */
+
+int nxagentXdmcpUp = 0;
+int nxagentXdmcpAlertUp = 0;
+
+/*
+ * Also used in the block, wakeup and
+ * sync handlers.
+ */
+
+int nxagentBuffer;
+int nxagentBlocking;
+int nxagentCongestion;
+
+double nxagentBytesIn;
+double nxagentBytesOut;
+
+/*
+ * Total number of descriptors ready
+ * as reported by the wakeup handler.
+ */
+
+int nxagentReady;
+
+/*
+ * Timestamp of the last write to the
+ * remote display.
+ */
+
+int nxagentFlush;
+
+/*
+ * Arbitrate the bandwidth among our
+ * clients.
+ */
+
+struct _TokensRec nxagentTokens = { 0, 0, 0 };
+struct _DispatchRec nxagentDispatch = { UNDEFINED, 0, 0, 0 };
+
+/*
+ * Called just before blocking, waiting
+ * for our clients or the X server.
+ */
+
+extern int nxagentSkipImage;
+
+void nxagentBlockHandler(void * data, struct timeval **timeout, void * mask)
+{
+ /*
+ * Zero timeout.
+ */
+
+ static struct timeval zero;
+
+ /*
+ * Current timestamp.
+ */
+
+ static int now;
+
+ /*
+ * Pending bytes to write to the
+ * network.
+ */
+
+ static int flushable;
+
+ /*
+ * Set if we need to synchronize
+ * any drawable.
+ */
+
+ static int synchronize;
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin block]\n");
+ #endif
+
+ now = GetTimeInMillis();
+
+ #ifdef NX_DEBUG_INPUT
+
+ if (nxagentDebugInputDevices == 1 &&
+ now - nxagentLastInputDevicesDumpTime > 5000)
+ {
+ nxagentLastInputDevicesDumpTime = now;
+
+ nxagentDumpInputDevicesState();
+ }
+
+ #endif
+
+ if (nxagentNeedConnectionChange() == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Calling nxagentHandleConnectionChanges "
+ "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup);
+ #endif
+
+ nxagentHandleConnectionChanges();
+ }
+
+ if (nxagentOption(Rootless) &&
+ nxagentLastWindowDestroyed && nxagentRootlessDialogPid == 0 &&
+ now > nxagentLastWindowDestroyedTime + 30 * 1000 && !nxagentOption(NoRootlessExit))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentBlockHandler: No application running. Closing the session.\n");
+ #endif
+
+ nxagentTerminateSession();
+ }
+
+ #ifdef TEST
+
+ if (nxagentLastWindowDestroyed == 1)
+ {
+ fprintf(stderr, "nxagentBlockHandler: Elapsed time [%lu].\n",
+ now - nxagentLastWindowDestroyedTime);
+ }
+
+ #endif
+
+ /*
+ * Slow down the agent if the session is
+ * not connected to a valid display.
+ */
+
+ if (NXDisplayError(nxagentDisplay) == 1 && nxagentShadowCounter == 0 && nxagentOption(SleepTime) > 0)
+ {
+#ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: sleeping for %d milliseconds for slowdown.\n",
+ nxagentOption(SleepTime));
+#endif
+ usleep(nxagentOption(SleepTime) * 1000);
+
+ now = GetTimeInMillis();
+ }
+#ifdef TEST
+ else if (0 == nxagentOption(SleepTime)) {
+ fprintf(stderr, "nxagentBlockHandler: not sleeping for slowdown.\n");
+ }
+#endif
+
+ /*
+ * Update the shadow display. This is
+ * only for test purposes.
+ */
+
+ #ifdef DUMP
+
+ nxagentPixmapOnShadowDisplay(NULL);
+
+ nxagentFbOnShadowDisplay();
+
+ #endif
+
+ /*
+ * We need this here because some window
+ * configuration changes can be generated
+ * by the X server outside the control of
+ * the DIX.
+ */
+
+ nxagentFlushConfigureWindow();
+
+ /*
+ * Check whether there is any drawable to
+ * synchronize.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Checking synchronization at %s with "
+ "[%d][%d][%d].\n", GetTimeInMillisAsString(), nxagentCorruptedWindows,
+ nxagentCorruptedBackgrounds, nxagentCorruptedPixmaps);
+ #endif
+
+ synchronize = (nxagentCorruptedWindows > 0 ||
+ nxagentCorruptedBackgrounds > 0 ||
+ nxagentCorruptedPixmaps > 0);
+
+ /*
+ * The synchronization function requires a mask as
+ * parameter:
+ *
+ * EVENT_BREAK Breaks if an user input, like
+ * a key press or a mouse move,
+ * is detected.
+ *
+ * CONGESTION_BREAK Breaks if the congestion beco-
+ * mes greater than 4.
+ *
+ * BLOCKING_BREAK Breaks if the display descript-
+ * or becomes blocked for write
+ * during the loop.
+ *
+ * ALWAYS_BREAK Any of the previous conditions
+ * is met.
+ *
+ * NEVER_BREAK The loop continues until all
+ * the drawables are synchronized.
+ */
+
+ if (synchronize == 1)
+ {
+ /*
+ * We should not enter the synchronization
+ * loop if there is any user input pending,
+ * i.e. if we are in the middle of a scroll
+ * operation.
+ */
+
+ if (nxagentForceSynchronization == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Going to force a synchronization at %s.\n",
+ GetTimeInMillisAsString());
+ #endif
+
+ nxagentSynchronizationLoop(NEVER_BREAK);
+
+ nxagentForceSynchronization = 0;
+ }
+ else if (nxagentUserInput(NULL) == 0 &&
+ nxagentBlocking == 0 &&
+ nxagentCongestion <= 4)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Going to synchronize at %s.\n",
+ GetTimeInMillisAsString());
+ #endif
+
+ nxagentSynchronizationLoop(ALWAYS_BREAK);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentBlockHandler: Not synchronizing with [%d][%d].\n",
+ nxagentBlocking, nxagentCongestion);
+ }
+ #endif
+
+ /*
+ * Check if we have more corrupted resources
+ * and whether the conditions are satisfied
+ * to continue with the synchronization.
+ */
+
+ synchronize = (nxagentCongestion <= 4 &&
+ (nxagentCorruptedWindows > 0 ||
+ nxagentCorruptedBackgrounds > 0 ||
+ nxagentCorruptedPixmaps > 0));
+
+ if (nxagentSkipImage == 0 && synchronize == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Setting a zero timeout with [%d][%d][%d] and "
+ "congestion [%d].\n", nxagentCorruptedWindows, nxagentCorruptedBackgrounds,
+ nxagentCorruptedPixmaps, nxagentCongestion);
+ #endif
+
+ zero.tv_sec = 0;
+ zero.tv_usec = 0;
+
+ *timeout = &zero;
+ }
+ #ifdef TEST
+ else
+ {
+ if (nxagentCorruptedWindows == 0 &&
+ nxagentCorruptedBackgrounds == 0 &&
+ nxagentCorruptedPixmaps == 0)
+ {
+ fprintf(stderr, "nxagentBlockHandler: Nothing more to synchronize at %s.\n",
+ GetTimeInMillisAsString());
+ }
+ else
+ {
+ fprintf(stderr, "nxagentBlockHandler: Delaying synchronization with [%d][%d][%d] and "
+ "congestion [%d].\n", nxagentCorruptedWindows, nxagentCorruptedBackgrounds,
+ nxagentCorruptedPixmaps, nxagentCongestion);
+ }
+ }
+ #endif
+ }
+
+ /*
+ * If the remote X server is blocking, reduce the
+ * amount of data sent in a single display update
+ * by reducing the size of the display buffer.
+ */
+
+ #ifdef DYNAMIC_DISPLAY_BUFFER
+
+ if (nxagentBlocking == 1 &&
+ nxagentBuffer > MINIMUM_DISPLAY_BUFFER)
+ {
+ nxagentBuffer >>= 1;
+
+ if (nxagentBuffer < MINIMUM_DISPLAY_BUFFER)
+ {
+ nxagentBuffer = MINIMUM_DISPLAY_BUFFER;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchHandler: Reducing the display buffer to [%d] bytes.\n",
+ nxagentBuffer);
+ #endif
+
+ NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer);
+ }
+ else if (nxagentBuffer < nxagentOption(DisplayBuffer) &&
+ nxagentCongestion == 0)
+ {
+ nxagentBuffer = nxagentOption(DisplayBuffer);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchHandler: Increasing the display buffer to [%d] bytes.\n",
+ nxagentBuffer);
+ #endif
+
+ NXSetDisplayBuffer(nxagentDisplay, nxagentBuffer);
+ }
+
+ #endif /* #ifdef DYNAMIC_DISPLAY_BUFFER */
+
+ /*
+ * Dispatch to the clients the events that
+ * may have become available.
+ */
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n");
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ /*
+ * Check if there is any data remaining,
+ * either in the display buffer or in
+ * the NX transport.
+ */
+
+ flushable = NXDisplayFlushable(nxagentDisplay);
+
+ if (flushable > 0)
+ {
+ #ifdef FLUSH_AFTER_MULTIPLE_READS
+
+ /*
+ * Flush all the outstanding data if
+ * the wakeup handler didn't detect
+ * any activity.
+ */
+
+ if (nxagentReady == 0 || now - nxagentFlush >=
+ nxagentOption(DisplayCoalescence))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBlockHandler: Flushing the display with [%d] bytes to flush.\n",
+ flushable);
+ #endif
+
+ NXFlushDisplay(nxagentDisplay, NXFlushLink);
+
+ /*
+ * New events may have become available
+ * after the flush.
+ */
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n");
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBlockHandler: Delaying flush with [%d][%d] and [%d] bytes.\n",
+ synchronize, nxagentReady, flushable);
+ #endif
+
+ zero.tv_sec = 0;
+ zero.tv_usec = 0;
+
+ *timeout = &zero;
+ }
+
+ #else /* #ifdef FLUSH_AFTER_MULTIPLE_READS */
+
+ /*
+ * We are entering the select. Tell the NX
+ * transport to write any produced data to
+ * the remote end.
+ */
+
+ NXFlushDisplay(nxagentDisplay, NXFlushLink);
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Reading the events available.\n");
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ #endif /* #ifdef FLUSH_AFTER_MULTIPLE_READS */
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBlockHandler: Nothing to flush with [%d][%d].\n",
+ synchronize, nxagentReady);
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 0 &&
+ nxagentQueuedEvents(nxagentDisplay) > 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentBlockHandler: WARNING! Forcing a null timeout with events queued.\n");
+ #endif
+
+ zero.tv_sec = 0;
+ zero.tv_usec = 0;
+
+ *timeout = &zero;
+ }
+ }
+
+ /*
+ * WaitForSomething() sets a zero timeout if there
+ * are clients with input, but doesn't stop the
+ * timer. The select is then interrupted to update
+ * the schedule time even if, what the dispatcher
+ * cares, is only the number of ticks at the time
+ * the client is scheduled in.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentBlockHandler: Stopping the smart schedule timer.\n");
+ #endif
+
+ nxagentStopTimer();
+
+ nxagentPrintGeometry();
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End block]\n");
+ #endif
+}
+
+void nxagentWakeupHandler(void * data, int count, void * mask)
+{
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin wakeup]\n");
+ #endif
+
+ if (nxagentException.sigHup || nxagentException.ioError)
+ {
+ #ifdef TEST
+ fprintf(stderr,"nxagentWakeupHandler: Got SIGHUP or I/O error.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: Calling nxagentHandleConnectionStates "
+ "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup);
+ #endif
+
+ nxagentHandleConnectionStates();
+ }
+
+ if (!SmartScheduleSignalEnable)
+ {
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWakeupHandler: Resetting the dispatch state after wakeup.\n");
+ #endif
+
+ nxagentDispatch.start = GetTimeInMillis();
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+
+ }
+
+ /*
+ * Can become true during the dispatch loop.
+ */
+
+ nxagentBlocking = 0;
+
+ /*
+ * Check if we got new events.
+ */
+
+ if (count > 0 && FD_ISSET(nxagentXConnectionNumber, (fd_set *) mask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentWakeupHandler: Reading the X events with count [%d].\n",
+ count);
+ #endif
+
+ nxagentDispatchEvents(NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWakeupHandler: Removing the X descriptor from the count.\n");
+ #endif
+
+ FD_CLR(nxagentXConnectionNumber, (fd_set *) mask);
+
+ count--;
+ }
+ else if (nxagentQueuedEvents(nxagentDisplay) == 1)
+ {
+ /*
+ * We may have left some events in
+ * the queue.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWakeupHandler: Reading the queued X events with count [%d].\n",
+ count);
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ /*
+ * Save the number of descriptors ready.
+ */
+
+ if (count <= 0)
+ {
+ count = (XFD_ANYSET(&ClientsWithInput) ? 1 : 0);
+ }
+
+ nxagentReady = count;
+
+ #ifdef TEST
+
+ if (nxagentReady == 0)
+ {
+ fprintf(stderr, "nxagentWakeupHandler: No X clients found to be processed.\n");
+ }
+
+ #endif
+
+ /*
+ * If the XDM connection can't be established
+ * we'll need to create a dialog to notify the
+ * user and give him/her a chance to terminate
+ * the session.
+ */
+
+ if (nxagentOption(Xdmcp) == 1 && nxagentXdmcpUp == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWakeupHandler: XdmcpState [%d].\n", XdmcpState);
+ #endif
+
+ if (XdmcpState == XDM_RUN_SESSION)
+ {
+ nxagentXdmcpUp = 1;
+ }
+
+ if (nxagentXdmcpUp == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWakeupHandler: XdmcpTime [%lu].\n",
+ GetTimeInMillis() - XdmcpStartTime);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentWakeupHandler: XdmcpTimeOutRtx [%d].\n",
+ XdmcpTimeOutRtx);
+ #endif
+
+ if (nxagentXdmcpAlertUp == 0 &&
+ GetTimeInMillis() - XdmcpStartTime >= XDM_TIMEOUT)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentWakeupHandler: WARNING! The XDM session seems to be "
+ "unable to start after [%ld] ms.\n",(long int)(GetTimeInMillis() - XdmcpStartTime));
+ #endif
+
+ NXTransAlert(FAILED_XDMCP_CONNECTION_ALERT, NX_ALERT_REMOTE);
+
+ nxagentXdmcpAlertUp = 1;
+ }
+ }
+ }
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End wakeup]\n");
+ #endif
+}
+
+void nxagentShadowBlockHandler(void * data, struct timeval **timeout, void * mask)
+{
+ static struct timeval zero;
+
+ int changed;
+ int suspended = 0;
+ int width_, height_;
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin block]\n");
+ #endif
+
+ if (nxagentNeedConnectionChange() == 1)
+ {
+ nxagentHandleConnectionChanges();
+ }
+
+ if (nxagentSessionState == SESSION_DOWN && nxagentOption(SleepTime) > 0)
+ {
+#ifdef TEST
+ fprintf(stderr, "nxagentBlockHandler: sleeping for %d milliseconds for slowdown.\n",
+ nxagentOption(SleepTime));
+#endif
+ usleep(nxagentOption(SleepTime) * 1000);
+ }
+#ifdef TEST
+ else if (0 == nxagentOption(SleepTime)) {
+ fprintf(stderr, "nxagentBlockHandler: not sleeping for slowdown.\n");
+ }
+#endif
+
+ #ifndef __CYGWIN32__
+
+ if (nxagentReadEvents(nxagentDisplay) > 0 ||
+ nxagentReadEvents(nxagentShadowDisplay) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowBlockHandler: Reading X events queued.\n");
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ if (nxagentShadowResize == 1)
+ {
+ nxagentShadowResize = 0;
+
+ nxagentShadowAdaptToRatio();
+ }
+
+ #else
+
+ if (nxagentReadEvents(nxagentDisplay) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowBlockHandler: Reading X events queued.\n");
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ #endif
+
+ changed = 0;
+
+ NXShadowGetScreenSize(&width_, &height_);
+
+ if (width_ != nxagentShadowWidth || height_ != nxagentShadowHeight)
+ {
+ /*
+ * The master session has been resized.
+ */
+
+ NXShadowSetScreenSize(&nxagentShadowWidth, &nxagentShadowHeight);
+
+ nxagentShadowAdaptToRatio();
+ }
+
+ nxagentShadowPoll(nxagentShadowPixmapPtr, nxagentShadowGCPtr, nxagentShadowDepth, nxagentShadowWidth,
+ nxagentShadowHeight, nxagentShadowBuffer, &changed, &suspended);
+
+ nxagentShadowSendUpdates(&suspended);
+
+ if (nxagentBlocking == 0)
+ {
+ nxagentSynchronizeDrawable((DrawablePtr) nxagentShadowPixmapPtr, DONT_WAIT,
+ ALWAYS_BREAK, nxagentShadowWindowPtr);
+ }
+
+ /*
+ * We are entering the select. Tell the NX
+ * transport to write any produced data to
+ * the remote end.
+ */
+/*
+FIXME: Must queue multiple writes and handle
+ the events by resembling the ordinary
+ block handler.
+*/
+
+ NXFlushDisplay(nxagentDisplay, NXFlushLink);
+
+ if (*timeout == NULL)
+ {
+ *timeout = &zero;
+ }
+
+ #ifdef __CYGWIN32__
+
+ if (nxagentOption(SleepTime) > 0) {
+#ifdef TEST
+ fprintf(stderr, "nxagentShadowBlockHandler: sleeping for %d milliseconds for slowdown.\n",
+ nxagentOption(SleepTime));
+#endif
+ usleep(nxagentOption(SleepTime) * 1000);
+ }
+#ifdef TEST
+ else if (0 == nxagentOption(SleepTime)) {
+ fprintf(stderr, "nxagentShadowBlockHandler: not sleeping for slowdown.\n");
+ }
+#endif
+
+ (*timeout) -> tv_sec = 0;
+ (*timeout) -> tv_usec = 50 * 1000;
+
+ #else
+
+ if (changed == 0)
+ {
+ (*timeout) -> tv_sec = 0;
+ (*timeout) -> tv_usec = 50 * 1000;
+ }
+ else
+ {
+ (*timeout) -> tv_sec = 0;
+ (*timeout) -> tv_usec = 0;
+ }
+
+ #endif
+
+ nxagentPrintGeometry();
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End block]\n");
+ #endif
+}
+
+void nxagentShadowWakeupHandler(void * data, int count, void * mask)
+{
+ #ifdef BLOCKS
+ fprintf(stderr, "[Begin wakeup]\n");
+ #endif
+
+ if (nxagentException.sigHup || nxagentException.ioError)
+ {
+ #ifdef TEST
+ fprintf(stderr,"nxagentShadowWakeupHandler: Got SIGHUP or I/O error.\n");
+ #endif
+
+ nxagentHandleConnectionStates();
+ }
+
+ if (!SmartScheduleSignalEnable)
+ {
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShadowWakeupHandler: Resetting the dispatch state after wakeup.\n");
+ #endif
+
+ nxagentDispatch.start = GetTimeInMillis();
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+
+ }
+
+ /*
+ * Can become true during the dispatch loop.
+ */
+
+ nxagentBlocking = 0;
+
+ /*
+ * Check if we got new events.
+ */
+
+ if (count > 0 && FD_ISSET(nxagentXConnectionNumber, (fd_set *) mask))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowWakeupHandler: Reading the X events with count [%d].\n",
+ count);
+ #endif
+
+ nxagentDispatchEvents(NULL);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowWakeupHandler: Removing the X descriptor from the count.\n");
+ #endif
+
+ FD_CLR(nxagentXConnectionNumber, (fd_set *) mask);
+
+ count--;
+ }
+ else if (nxagentQueuedEvents(nxagentDisplay) == 1)
+ {
+ /*
+ * We may have left some events in
+ * the queue.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowWakeupHandler: Reading the queued X events with count [%d].\n",
+ count);
+ #endif
+
+ nxagentDispatchEvents(NULL);
+ }
+
+ /*
+ * Save the number of descriptors ready.
+ */
+
+ if (count <= 0)
+ {
+ count = (XFD_ANYSET(&ClientsWithInput) ? 1 : 0);
+ }
+
+ nxagentReady = count;
+
+ #ifdef TEST
+
+ if (nxagentReady == 0)
+ {
+ fprintf(stderr, "nxagentShadowWakeupHandler: No X clients found to be processed.\n");
+ }
+
+ #endif
+
+ #ifdef BLOCKS
+ fprintf(stderr, "[End wakeup]\n");
+ #endif
+}
+
+void nxagentHandleCollectInputFocusEvent(int resource)
+{
+ /*
+ * While we don't even need window or revert_to later on, a discrepancy in
+ * data type sizes between the X server (Window being a 32bit ID) and
+ * the Xlib (Window being a 64bit ID) will lead to stack corruption here.
+ * Calling functions from CompExt from nxagent sounds like a very bad idea
+ * to begin with, but let's assume that's necessary for now and work around
+ * the corruption issue.
+ *
+ * Even though the CompExt header shows that the function expects a Window-sized
+ * parameter, it's not the Window type as defined and used within the X.Org
+ * Server, but an Xlib type. Hence, we'll be using the "XlibWindow" type here
+ * and to avoid compiler warnings, "rewrite" the CompExt.h header file via
+ * overriding the original "Window" type with the XlibWindow type, including
+ * the header file and undefining the macro again, essentially unshadowing
+ * the original type.
+ */
+ XlibWindow window;
+
+ int revert_to;
+
+ if (NXGetCollectedInputFocus(nxagentDisplay, resource, &window, &revert_to) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleCollectInputFocusEvent: PANIC! Failed to get the input focus "
+ "reply for resource [%d].\n", resource);
+ #endif
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentHandleCollectInputFocusEvent: Received a sync reply with [%d] pending.\n",
+ nxagentTokens.pending);
+ #endif
+
+ nxagentTokens.pending--;
+
+ nxagentCongestion = (nxagentTokens.pending >= TOKENS_PENDING_LIMIT / 2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleCollectInputFocusEvent: Current congestion level is [%d].\n",
+ nxagentCongestion);
+ #endif
+}
+
+Bool nxagentCollectInputFocusPredicate(Display *display, XEvent *X, XPointer ptr)
+{
+ return (X -> xclient.window == 0 &&
+ X -> xclient.message_type == 0 &&
+ X -> xclient.format == 32 &&
+ X -> xclient.data.l[0] == NXCollectInputFocusNotify);
+}
+
+void nxagentDispatchHandler(ClientPtr client, int in, int out)
+{
+ /*
+ * This function is called by the dispatcher (with 0
+ * bytes out) after a new request has been processed.
+ * It is also called by the write handler (with 0
+ * bytes in) after more data has been written to the
+ * display. It may be optionally called in the block
+ * and wakeup handlers. In this case both in and out
+ * must be 0.
+ */
+
+ if (out > 0)
+ {
+ /*
+ * Called by the display write callback.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Called with [%d] bytes written.\n",
+ out);
+ #endif
+
+ nxagentBytesOut += out;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Total bytes are [%.0f] in [%.0f] out.\n",
+ nxagentBytesIn, nxagentBytesOut);
+ #endif
+
+ /*
+ * Don't take care of the synchronization if
+ * the NX transport is running. The NX trans-
+ * port has its own token-based control flow.
+ *
+ * We can't produce more output here because
+ * we are in the middle of the flush. We will
+ * take care of the sync requests when called
+ * by the dispatcher.
+ */
+
+ if (nxagentOption(LinkType) == LINK_TYPE_NONE)
+ {
+ nxagentTokens.soft += out;
+
+ if (out > BYTES_BEFORE_HARD_TOKEN)
+ {
+ nxagentTokens.hard += out;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Sync bytes accumulated are [%d] and [%d].\n",
+ nxagentTokens.soft, nxagentTokens.hard);
+ #endif
+ }
+
+ if (!SmartScheduleSignalEnable)
+ {
+
+ /*
+ * Pay attention to the next client if this
+ * client produced enough output.
+ */
+
+ if (nxagentBytesOut - nxagentDispatch.out > BYTES_BEFORE_YIELD)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Yielding with [%ld][%.0f][%.0f] for client [%d].\n",
+ GetTimeInMillis() - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in,
+ nxagentBytesOut - nxagentDispatch.out, nxagentDispatch.client);
+ #endif
+
+ nxagentDispatch.start = GetTimeInMillis();
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+
+ isItTimeToYield = 1;
+ }
+ #ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "nxagentDispatchHandler: Dispatching with [%ld][%.0f][%.0f] for client [%d].\n",
+ GetTimeInMillis() - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in,
+ nxagentBytesOut - nxagentDispatch.out, nxagentDispatch.client);
+ }
+ #endif
+
+ }
+
+ return;
+ }
+ else if (in > 0)
+ {
+ /*
+ * Called by the dispatcher.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Called with [%d] bytes processed for client [%d].\n",
+ in, client -> index);
+ #endif
+
+ /*
+ * This is presently unused.
+ *
+ * nxagentClientAddBytes(client, in);
+ *
+ * #ifdef DEBUG
+ * fprintf(stderr, "nxagentDispatchHandler: Bytes processed for client [%d] are [%ld].\n",
+ * client -> index, nxagentClientBytes(client));
+ * #endif
+ *
+ */
+
+ nxagentBytesIn += in;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Total bytes are [%.0f] in [%.0f] out.\n",
+ nxagentBytesIn, nxagentBytesOut);
+ #endif
+
+ /*
+ * When using the dumb scheduler, before reading from
+ * another client, the dispatcher tries to drain all
+ * the input from the client being processed. This
+ * means that, if isItTimeToYield is never set and the
+ * client never produces any output, we'll stick into
+ * the inner dispatch loop forever.
+ */
+
+ if (!SmartScheduleSignalEnable)
+ {
+
+ if (client -> index != nxagentDispatch.client)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Resetting the dispatch state with [%d][%d].\n",
+ nxagentDispatch.client, client -> index);
+ #endif
+
+ nxagentDispatch.client = client -> index;
+ nxagentDispatch.start = GetTimeInMillis();
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+ }
+ else
+ {
+ static unsigned long int now;
+
+ now = GetTimeInMillis();
+
+ if (now - nxagentDispatch.start > TIME_BEFORE_YIELD ||
+ nxagentBytesIn - nxagentDispatch.in > BYTES_BEFORE_YIELD)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Yielding with [%ld][%.0f][%.0f] for client [%d].\n",
+ now - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, nxagentBytesOut -
+ nxagentDispatch.out, nxagentDispatch.client);
+ #endif
+
+ nxagentDispatch.start = now;
+
+ nxagentDispatch.in = nxagentBytesIn;
+ nxagentDispatch.out = nxagentBytesOut;
+
+ isItTimeToYield = 1;
+ }
+ #ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "nxagentDispatchHandler: Dispatching with [%ld][%.0f][%.0f] for client [%d].\n",
+ now - nxagentDispatch.start, nxagentBytesIn - nxagentDispatch.in, nxagentBytesOut -
+ nxagentDispatch.out, nxagentDispatch.client);
+ }
+ #endif
+ }
+
+ }
+
+ }
+
+ /*
+ * Let's see if it's time to sync.
+ */
+
+ if (nxagentOption(LinkType) == LINK_TYPE_NONE)
+ {
+ if (nxagentTokens.hard > BYTES_BEFORE_HARD_TOKEN)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Requesting a hard sync reply with [%d] bytes.\n",
+ nxagentTokens.hard);
+ #endif
+
+ XSync(nxagentDisplay, 0);
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ nxagentDispatchEvents(NULL);
+ }
+
+ nxagentTokens.soft = 0;
+ nxagentTokens.hard = 0;
+ }
+ else if (nxagentTokens.soft > BYTES_BEFORE_SOFT_TOKEN)
+ {
+ /*
+ * Alternatively, the amounts of bytes
+ * accounted for each sync request may
+ * be decreased according to the number
+ * of pending replies already awaited.
+ *
+ * else if (nxagentTokens.soft > (BYTES_BEFORE_SOFT_TOKEN / (nxagentTokens.pending + 1)))
+ */
+
+ int resource;
+
+ /*
+ * Wait eventually for the number of
+ * synchronization requests to return
+ * below the limit.
+ */
+
+ #ifdef TEST
+
+ if (nxagentTokens.pending == TOKENS_PENDING_LIMIT)
+ {
+ fprintf(stderr, "nxagentDispatchHandler: WARNING! Waiting for the synchronization reply.\n");
+ }
+
+ #endif
+
+ while (nxagentTokens.pending == TOKENS_PENDING_LIMIT)
+ {
+ if (nxagentWaitEvents(nxagentDisplay, NULL) == -1)
+ {
+ nxagentTokens.pending = 0;
+
+ nxagentTokens.soft = 0;
+
+ return;
+ }
+
+ nxagentDispatchEvents(NULL);
+
+ nxagentBlocking = 1;
+ }
+
+ /*
+ * Send a new synchronization request.
+ */
+
+ resource = nxagentWaitForResource(NXGetCollectInputFocusResource,
+ nxagentCollectInputFocusPredicate);
+
+ if (resource == -1)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentDispatchHandler: PANIC! Cannot allocate any valid resource.\n");
+ #endif
+
+ nxagentTokens.soft = 0;
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDispatchHandler: Requesting a sync reply with [%d] bytes "
+ "and [%d] pending.\n", nxagentTokens.soft, nxagentTokens.pending);
+ #endif
+
+ NXCollectInputFocus(nxagentDisplay, resource);
+
+ NXFlushDisplay(nxagentDisplay, NXFlushBuffer);
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ nxagentDispatchEvents(NULL);
+ }
+
+ nxagentTokens.pending++;
+
+ nxagentCongestion = (nxagentTokens.pending >= TOKENS_PENDING_LIMIT / 2);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDispatchHandler: Current congestion level is [%d].\n",
+ nxagentCongestion);
+ #endif
+
+ nxagentTokens.soft = 0;
+ }
+ }
+
+ /*
+ * Check if there are events to read.
+ */
+
+ if (nxagentPendingEvents(nxagentDisplay) > 0)
+ {
+ nxagentDispatchEvents(NULL);
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Handlers.h b/nx-X11/programs/Xserver/hw/nxagent/Handlers.h
new file mode 100644
index 000000000..ddae097da
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Handlers.h
@@ -0,0 +1,129 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Handlers_H__
+#define __Handlers_H__
+
+/*
+ * Current size of the display buffer.
+ */
+
+extern int nxagentBuffer;
+
+/*
+ * Set if we had to block waiting for
+ * the display to become writable.
+ */
+
+extern int nxagentBlocking;
+
+/*
+ * Current congestion level based on
+ * the sync requests awaited or the
+ * proxy tokens.
+ */
+
+extern int nxagentCongestion;
+
+/*
+ * Bytes read from the agent's clients
+ * and written to the display socket.
+ */
+
+extern double nxagentBytesIn;
+extern double nxagentBytesOut;
+
+/*
+ * Total number of descriptors ready
+ * as reported by the wakeup handler.
+ */
+
+extern int nxagentReady;
+
+/*
+ * Timestamp of the last write to the
+ * remote display.
+ */
+
+extern int nxagentFlush;
+
+/*
+ * Let the dispatch loop yield control to
+ * a different client after a fair amount
+ * of time or after enough data has been
+ * processed.
+ */
+
+struct _DispatchRec
+{
+ int client;
+
+ double in;
+ double out;
+
+ unsigned long start;
+};
+
+extern struct _DispatchRec nxagentDispatch;
+
+/*
+ * Ensure that we synchronize with the X
+ * server after a given amount of output
+ * is produced.
+ */
+
+struct _TokensRec
+{
+ int soft;
+ int hard;
+
+ int pending;
+};
+
+extern struct _TokensRec nxagentTokens;
+
+/*
+ * The agent's block and wakeup handlers.
+ */
+
+void nxagentBlockHandler(void * data, struct timeval **timeout, void * mask);
+void nxagentWakeupHandler(void * data, int count, void * mask);
+
+/*
+ * Executed after each request processed.
+ */
+
+void nxagentDispatchHandler(ClientPtr client, int in, int out);
+
+void nxagentShadowBlockHandler(void * data, struct timeval **timeout, void * mask);
+void nxagentShadowWakeupHandler(void * data, int count, void * mask);
+
+extern GCPtr nxagentShadowGCPtr;
+extern unsigned char nxagentShadowDepth;
+extern int nxagentShadowWidth;
+extern int nxagentShadowHeight;
+extern char *nxagentShadowBuffer;
+
+#endif /* __Handlers_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Holder.c b/nx-X11/programs/Xserver/hw/nxagent/Holder.c
new file mode 100644
index 000000000..aae48471b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.c
@@ -0,0 +1,235 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <signal.h>
+#include <stdio.h>
+
+#ifdef _XSERVER64
+
+#include "scrnintstr.h"
+#include "Agent.h"
+#define GC XlibGC
+#define Pixmap XlibPixmap
+#define PIXEL_ALREADY_TYPEDEFED
+
+#endif /* _XSERVER64 */
+
+#include "pixmapstr.h"
+#include "regionstr.h"
+#include "resource.h"
+#include "../../include/gc.h"
+#include "../../include/window.h"
+
+#include "X11/include/xpm_nxagent.h"
+
+#include "Agent.h"
+#include "Pixmaps.h"
+#include "Display.h"
+#include "Holder.h"
+#include "Icons.h"
+
+#include NXAGENT_PLACEHOLDER_NAME
+
+#define MAXDEPTH 32
+
+#define PLACEHOLDER_WIDTH 14
+#define PLACEHOLDER_HEIGHT 16
+
+#define PLACEHOLDER_BORDER_COLOR_DARK 0x000000
+#define PLACEHOLDER_BORDER_COLOR_LIGHT 0xB2B2B2
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+static Pixmap nxagentPlaceholderPixmaps[MAXDEPTH + 1];
+
+void nxagentMarkPlaceholderNotLoaded(int depth)
+{
+ nxagentPlaceholderPixmaps[depth] = 0;
+}
+
+void nxagentInitPlaceholder(int depth)
+{
+ int status;
+ XpmAttributes attributes;
+
+ attributes.valuemask = XpmDepth | XpmSize;
+ attributes.depth = depth;
+
+ status = XpmCreatePixmapFromData(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ placeholderXpm, nxagentPlaceholderPixmaps + depth, NULL, &attributes);
+
+ if (status != Success)
+ {
+ FatalError("Error: Failed to create the placeholder pixmap.\n");
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitPlaceholder: Created pixmap [0x%lx] with geometry [%d,%d] for depth [%d].\n",
+ nxagentPlaceholderPixmaps[depth], attributes.width, attributes.height, depth);
+ #endif
+}
+
+void nxagentApplyPlaceholder(Drawable drawable, int x, int y,
+ int w, int h, int depth)
+{
+ /*
+ * Instead of the image, a white rectangle that
+ * covers the pixmap area is drawn, alongside
+ * with a black and grey line that outlines the
+ * boundaries of the affected area.
+ */
+
+ GC gc;
+ XGCValues value;
+ XPoint points[3];
+
+ value.foreground = 0xffffffff;
+ value.background = 0x00000000;
+ value.plane_mask = 0xffffffff;
+ value.fill_style = FillSolid;
+
+ /*
+ * FIXME: Should we use a gc cache to save
+ * some bandwidth?
+ */
+
+ gc = XCreateGC(nxagentDisplay, drawable, GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ XFillRectangle(nxagentDisplay, drawable, gc, x, y, w, h);
+
+ if (depth == 1)
+ {
+ return;
+ }
+
+ value.foreground = PLACEHOLDER_BORDER_COLOR_DARK;
+ value.line_style = LineSolid;
+ value.line_width = 1;
+
+ points[0].x = x;
+ points[0].y = y + h - 1;
+ points[1].x = x;
+ points[1].y = y;
+ points[2].x = x + w - 1;
+ points[2].y = y;
+
+ XChangeGC(nxagentDisplay, gc, GCForeground | GCLineWidth | GCLineStyle, &value);
+ XDrawLines(nxagentDisplay, drawable, gc, points, 3, CoordModeOrigin);
+
+ value.foreground = PLACEHOLDER_BORDER_COLOR_LIGHT;
+ value.line_style = LineSolid;
+ value.line_width = 1;
+
+ points[0].x = x;
+ points[0].y = y + h - 1;
+ points[1].x = x + w - 1;
+ points[1].y = y + h - 1;
+ points[2].x = x + w - 1;
+ points[2].y = y;
+
+ XChangeGC(nxagentDisplay, gc, GCForeground | GCLineWidth | GCLineStyle, &value);
+ XDrawLines(nxagentDisplay, drawable, gc, points, 3, CoordModeOrigin);
+
+ /*
+ * We are going to apply place holder only if on region
+ * we have enough space for the placeholder plus three
+ * pixel for spacing and one for region border.
+ */
+
+ if ((w >= PLACEHOLDER_WIDTH + 8) && (h >= PLACEHOLDER_HEIGHT + 8))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentApplyPlaceholder: drawable %lx placeholder %lx from %d %d pixmap size is %d %d "
+ "depth %d\n", drawable, nxagentPlaceholderPixmaps[depth], x, y, w, h, depth);
+ #endif
+
+ if (nxagentPlaceholderPixmaps[depth] == 0)
+ {
+ nxagentInitPlaceholder(depth);
+ }
+
+ XCopyArea(nxagentDisplay, nxagentPlaceholderPixmaps[depth],
+ drawable, gc, 0, 0, PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, x + 4, y + 4);
+
+ }
+
+ XFreeGC(nxagentDisplay, gc);
+
+ return;
+}
+
+#ifdef DUMP
+
+static char hexdigit(char c)
+{
+ char map[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '?'};
+
+ return map[c];
+}
+
+/*
+FIXME: Please, check the implementation of the same
+ function in nxcomp.
+*/
+char *nxagentChecksum(char *string, int length)
+{
+ static char md5_output[MD5_DIGEST_LENGTH * 2 + 1];
+ static char md5[MD5_DIGEST_LENGTH];
+ char * ret;
+ int i;
+
+ memset(md5, 0, sizeof(md5));
+ memset(md5_output, 0, sizeof(md5_output));
+
+ ret = MD5(string, length, md5);
+
+ for (i = 0; i < MD5_DIGEST_LENGTH; i++)
+ {
+ char c = md5[i];
+
+ md5_output[i * 2 + 0] = hexdigit((c >> 0) & 0xF);
+ md5_output[i * 2 + 1] = hexdigit((c >> 4) & 0xF);
+ }
+
+ return md5_output;
+}
+
+#else
+
+const char *nxagentChecksum(char *data, int size)
+{
+ return "";
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Holder.h b/nx-X11/programs/Xserver/hw/nxagent/Holder.h
new file mode 100644
index 000000000..d1378ee03
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Holder.h
@@ -0,0 +1,35 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Holder_H__
+#define __Holder_H__
+
+void nxagentMarkPlaceholderNotLoaded(int depth);
+void nxagentInitPlaceholder(int depth);
+void nxagentApplyPlaceholder(Drawable drawable, int x, int y, int w, int h, int depth);
+
+const char *nxagentChecksum(char *data, int size);
+
+#endif /* __Holder_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Icons.h b/nx-X11/programs/Xserver/hw/nxagent/Icons.h
new file mode 100644
index 000000000..a87a5a112
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Icons.h
@@ -0,0 +1,39 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Icons_H__
+#define __Icons_H__
+
+#define Pixel XpmPixel
+#include "X11/include/xpm_nxagent.h"
+#undef Pixel
+
+#define NXAGENT_ICON_NAME "nxagent.xpm"
+
+#define X2GOAGENT_ICON_NAME "x2go.xpm"
+
+#define NXAGENT_PLACEHOLDER_NAME "nxmissing.xpm"
+
+#endif /* __Icons_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Image.c b/nx-X11/programs/Xserver/hw/nxagent/Image.c
new file mode 100644
index 000000000..590f0b249
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Image.c
@@ -0,0 +1,1828 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "scrnintstr.h"
+#include "resource.h"
+#include "dixstruct.h"
+#include "../../fb/fb.h"
+
+#include "Agent.h"
+#include "Composite.h"
+#include "Display.h"
+#include "Visual.h"
+#include "Drawable.h"
+#include "Pixmaps.h"
+#include "GCs.h"
+#include "Image.h"
+#include "Events.h"
+#include "Client.h"
+#include "Trap.h"
+#include "Split.h"
+#include "Args.h"
+#include "Screen.h"
+#include "Pixels.h"
+#include "Utils.h"
+
+#include "compext/Compext.h"
+#include <nx/NXpack.h>
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * Don't pack the images having a width, a
+ * height or a data size smaller or equal
+ * to these thresholds.
+ */
+
+#define IMAGE_PACK_WIDTH 2
+#define IMAGE_PACK_HEIGHT 2
+#define IMAGE_PACK_LENGTH 512
+
+/*
+ * Compress the image with a lossless encoder
+ * if the percentage of discrete pixels in the
+ * image is below this threshold.
+ */
+
+#define IMAGE_UNIQUE_RATIO 10
+
+/*
+ * Preferred pack and split parameters we
+ * got from the NX transport.
+ */
+
+int nxagentPackLossless = -1;
+int nxagentPackMethod = -1;
+int nxagentPackQuality = -1;
+int nxagentSplitThreshold = -1;
+
+/*
+ * Set if images can use the alpha channel.
+ */
+
+int nxagentAlphaEnabled = 0;
+int nxagentAlphaCompat = 0;
+
+/*
+ * Used to reformat image when connecting to
+ * displays having different byte order.
+ */
+
+extern void nxagentBitOrderInvert(unsigned char *, int);
+extern void nxagentTwoByteSwap(unsigned char *, register int);
+extern void nxagentFourByteSwap(register unsigned char *, register int);
+
+/*
+ * Store the last visual used to unpack
+ * the images for the given client.
+ */
+
+static VisualID nxagentUnpackVisualId[MAX_CONNECTIONS];
+
+/*
+ * Store the last alpha data set for the
+ * client.
+ */
+
+typedef struct _UnpackAlpha
+{
+ char *data;
+ int size;
+
+} UnpackAlphaRec;
+
+typedef UnpackAlphaRec *UnpackAlphaPtr;
+
+static UnpackAlphaPtr nxagentUnpackAlpha[MAX_CONNECTIONS];
+
+/*
+ * Encode the imade alpha channel by using
+ * a specific encoding, separating it from
+ * the rest of the RGB data.
+ */
+
+static char *nxagentImageAlpha(XImage *ximage);
+static void nxagentSetUnpackAlpha(DrawablePtr pDrawable, XImage *pImage, ClientPtr pClient);
+
+/*
+ * Copy the source data to the destination.
+ */
+
+static char *nxagentImageCopy(XImage *source, XImage *destination);
+
+/*
+ * Return true if the image can be cached.
+ * Don't cache the images packed with the
+ * bitmap method as the encoding is little
+ * more expensive than a copy.
+ */
+
+#define nxagentNeedCache(image, method) \
+\
+ ((method) != PACK_BITMAP_16M_COLORS)
+
+/*
+ * With the bitmap encoding, if the image
+ * is 32 bits-per-pixel the 4th byte is not
+ * transmitted, so we don't need to clean
+ * the image.
+ */
+
+#define nxagentNeedClean(image, method) \
+\
+ ((method) == PACK_RLE_16M_COLORS || \
+ (method) == PACK_RGB_16M_COLORS || \
+ ((method) == PACK_BITMAP_16M_COLORS && \
+ image -> bits_per_pixel != 32))
+
+/*
+ * Collect the image cache statistics.
+ */
+
+typedef struct _ImageStatisticsRec
+{
+ double partialLookups;
+ double partialMatches;
+ double partialEncoded;
+ double partialAdded;
+
+ double totalLookups;
+ double totalMatches;
+ double totalEncoded;
+ double totalAdded;
+
+} ImageStatisticsRec;
+
+ImageStatisticsRec nxagentImageStatistics;
+
+int nxagentImageReformat(char *base, int nbytes, int bpp, int order)
+{
+ /*
+ * This is used whenever we need to swap the image data.
+ * If we got an image from a X server having a different
+ * endianess, we will need to redormat the image to match
+ * our own image-order so that ProcGetImage can return
+ * the expected format to the client.
+ */
+
+ switch (bpp)
+ {
+ case 1:
+ {
+ if (BITMAP_BIT_ORDER != order)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImageReformat: Bit order invert with size [%d] "
+ "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order);
+ #endif
+
+ nxagentBitOrderInvert((unsigned char *) base, nbytes);
+ }
+
+ #if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
+
+ nxagentImageReformat(base, nbytes, BITMAP_SCANLINE_UNIT, order);
+
+ #endif
+
+ break;
+ }
+ case 4:
+ case 8:
+ {
+ break;
+ }
+ case 16:
+ {
+ if (IMAGE_BYTE_ORDER != order)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImageReformat: Two bytes swap with size [%d] "
+ "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order);
+ #endif
+
+ nxagentTwoByteSwap((unsigned char *) base, nbytes);
+ }
+
+ break;
+ }
+ case 32:
+ {
+ if (IMAGE_BYTE_ORDER != order)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImageReformat: Four bytes swap with size [%d] "
+ "bits per pixel [%d] byte order [%d].\n", nbytes, bpp, order);
+ #endif
+
+ nxagentFourByteSwap((unsigned char *) base, nbytes);
+ }
+
+ break;
+ }
+ }
+
+ return 1;
+}
+
+int nxagentImageLength(int width, int height, int format, int leftPad, int depth)
+{
+ int line = 0;
+
+ if (format == XYBitmap)
+ {
+ line = BitmapBytePad(width + leftPad);
+ }
+ else if (format == XYPixmap)
+ {
+ line = BitmapBytePad(width + leftPad);
+
+ line *= depth;
+ }
+ else if (format == ZPixmap)
+ {
+ line = PixmapBytePad(width, depth);
+ }
+
+ return line * height;
+}
+
+int nxagentImagePad(int width, int format, int leftPad, int depth)
+{
+ int line = 0;
+
+ if (format == XYBitmap)
+ {
+ line = BitmapBytePad(width + leftPad);
+ }
+ else if (format == XYPixmap)
+ {
+ line = BitmapBytePad(width + leftPad);
+ }
+ else if (format == ZPixmap)
+ {
+ line = PixmapBytePad(width, depth);
+ }
+
+ return line;
+}
+
+/*
+ * Only copy the data, not the structure.
+ * The data pointed by the destination is
+ * lost. Used to clone two images that
+ * point to the same data.
+ */
+
+char *nxagentImageCopy(XImage *source, XImage *destination)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentImageClone: Copying [%d] bytes of data from the source.\n",
+ source -> bytes_per_line * source -> height);
+ #endif
+
+ destination -> data = Xmalloc(source -> bytes_per_line * source -> height);
+
+ if (destination -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentImageCopy: PANIC! Cannot allocate memory for the copy.\n");
+ #endif
+ }
+ else
+ {
+ memcpy(destination -> data, source -> data,
+ source -> bytes_per_line * source -> height);
+ }
+
+ return destination -> data;
+}
+
+char *nxagentImageAlpha(XImage *image)
+{
+ char *pData;
+
+ char *pSrcData;
+ char *pDstData;
+
+ int size;
+ int offset;
+
+ /*
+ * Use one byte per pixel.
+ */
+
+ size = (image -> bytes_per_line * image -> height) >> 2;
+
+ pData = Xmalloc(size);
+
+ if (pData == NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ * The image is supposed to be in
+ * server order.
+ */
+
+ offset = (image -> byte_order == MSBFirst) ? 0 : 3;
+
+ pSrcData = image -> data;
+ pDstData = pData;
+
+ while (size-- > 0)
+ {
+ *pDstData++ = *(pSrcData + offset);
+
+ pSrcData += 4;
+ }
+
+ return pData;
+}
+
+/*
+ * Write down the image cache statistics
+ * to the buffer.
+ */
+
+void nxagentImageStatisticsHandler(char **buffer, int type)
+{
+/*
+FIXME: Agent cache statistics have to be implemented.
+*/
+ #ifdef TEST
+ fprintf(stderr, "nxagentImageStatisticsHandler: STATISTICS! Statistics requested to the agent.\n");
+ #endif
+
+ *buffer = NULL;
+}
+
+/*
+ * This should be called only for drawables
+ * having a depth of 32. In the other cases,
+ * it would only generate useless traffic.
+ */
+
+void nxagentSetUnpackAlpha(DrawablePtr pDrawable, XImage *pImage, ClientPtr pClient)
+{
+ int resource = pClient -> index;
+
+ unsigned int size = (pImage -> bytes_per_line * pImage -> height) >> 2;
+
+ char *data = nxagentImageAlpha(pImage);
+
+ if (data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSetUnpackAlpha: PANIC! Can't allocate data for the alpha channel.\n");
+ #endif
+
+ return;
+ }
+
+ /*
+ * If we are synchronizing the drawable, discard
+ * any unpack alpha stored for the client. The
+ * alpha data, in fact, may be still traveling
+ * and so we either wait until the end of the
+ * split or send a fresh copy.
+ */
+/*
+FIXME: Here the split trap is always set and so the caching of
+ the alpha channel is useless. I remember we set the trap
+ because of the cursor but why is it always set now?
+*/
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetUnpackAlpha: Checking alpha channel for client [%d] with trap [%d].\n",
+ resource, nxagentSplitTrap);
+ #endif
+
+ if (nxagentSplitTrap == 1 || nxagentUnpackAlpha[resource] == NULL ||
+ nxagentUnpackAlpha[resource] -> size != size ||
+ memcmp(nxagentUnpackAlpha[resource] -> data, data, size) != 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetUnpackAlpha: Sending alpha channel with width [%d] height [%d] "
+ "bytes per line [%d] size [%d].\n", pImage -> width, pImage -> height,
+ pImage -> bytes_per_line, size);
+ #endif
+
+ /*
+ * Check if we are connected to a newer proxy
+ * version and so can send the alpha data in
+ * compressed form.
+ */
+
+ if (nxagentAlphaCompat == 0)
+ {
+ NXSetUnpackAlpha(nxagentDisplay, resource, PACK_NONE, size, data, size);
+ }
+ else
+ {
+ NXSetUnpackAlphaCompat(nxagentDisplay, resource, size, data);
+ }
+
+ if (nxagentUnpackAlpha[resource] != NULL)
+ {
+ free(nxagentUnpackAlpha[resource] -> data);
+ }
+ else if ((nxagentUnpackAlpha[resource] = Xmalloc(sizeof(UnpackAlphaRec))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSetUnpackAlpha: PANIC! Can't allocate data for the alpha structure.\n");
+ #endif
+
+ free(data);
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetUnpackAlpha: Saved alpha channel for client [%d] with size [%d].\n",
+ resource, size);
+ #endif
+
+ nxagentUnpackAlpha[resource] -> size = size;
+ nxagentUnpackAlpha[resource] -> data = data;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSetUnpackAlpha: Matched alpha channel for client [%d] with size [%d].\n",
+ resource, size);
+ #endif
+
+ free(data);
+ }
+}
+
+/*
+ * The NX agent's implementation of the
+ * X server's image functions.
+ */
+
+void nxagentPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int dstX, int dstY, int dstWidth, int dstHeight,
+ int leftPad, int format, char *data)
+{
+ int length;
+
+ RegionPtr pRegion = NullRegion;
+
+ int resource = 0;
+ int split = 0;
+ int cache = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Image data at [%p] drawable [%s][%p] geometry [%d,%d,%d,%d].\n",
+ data, (pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window"),
+ (void *) pDrawable, dstX, dstY, dstWidth, dstHeight);
+ #endif
+
+ /*
+ * If the display is down and there is not an
+ * nxagent attached, sleep for a while but
+ * still give a chance to the client to write
+ * to the framebuffer.
+ */
+
+ length = nxagentImageLength(dstWidth, dstHeight, format, leftPad, depth);
+
+ if (nxagentShadowCounter == 0 &&
+ NXDisplayError(nxagentDisplay) == 1 &&
+ nxagentOption(SleepTime) > 0)
+ {
+ int us;
+
+ us = nxagentOption(SleepTime) * 4 * (length / 1024);
+
+ us = (us < 10000 ? 10000 : (us > 1000000 ? 1000000 : us));
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutImage: Sleeping for [%d] milliseconds with length [%d] and link down.\n",
+ us / 1000, length);
+ #endif
+
+ usleep(us);
+ }
+
+ /*
+ * This is of little use because clients usually write
+ * to windows only after an expose event, and, in the
+ * rare case they use a direct put image to the window
+ * (for a media player it should be a necessity), they
+ * are likely to monitor the visibility of the window.
+ */
+
+ if (nxagentOption(IgnoreVisibility) == 0 && pDrawable -> type == DRAWABLE_WINDOW &&
+ (nxagentWindowIsVisible((WindowPtr) pDrawable) == 0 ||
+ (nxagentDefaultWindowIsVisible() == 0 && nxagentCompositeEnable == 0)))
+ {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on fully obscured "
+ "window at [%p].\n", (void *) pDrawable);
+ #endif
+
+ goto nxagentPutImageEnd;
+ }
+
+ /*
+ * This is more interesting. Check if the operation
+ * will produce a visible result based on the clip
+ * list of the window and the GC.
+ */
+
+ pRegion = nxagentCreateRegion(pDrawable, pGC, dstX, dstY, dstWidth, dstHeight);
+
+ if (RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on fully clipped "
+ "region [%d,%d,%d,%d] for drawable at [%p].\n", pRegion -> extents.x1,
+ pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2,
+ (void *) pDrawable);
+ #endif
+
+ goto nxagentPutImageEnd;
+ }
+
+/*
+FIXME: Should use these.
+
+ int framebuffer = 1;
+ int realize = 1;
+*/
+ if (nxagentGCTrap == 1 && nxagentReconnectTrap == 0 &&
+ nxagentFBTrap == 0 && nxagentShmTrap == 0)
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ fbPutImage(nxagentVirtualDrawable(pDrawable), pGC, depth,
+ dstX, dstY, dstWidth, dstHeight, leftPad, format, data);
+ }
+ else
+ {
+ fbPutImage(pDrawable, pGC, depth,
+ dstX, dstY, dstWidth, dstHeight, leftPad, format, data);
+ }
+
+ goto nxagentPutImageEnd;
+ }
+
+ if (nxagentReconnectTrap == 0 &&
+ nxagentSplitTrap == 0)
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentFBTrap == 0 && nxagentShmTrap == 0)
+ {
+ fbPutImage(nxagentVirtualDrawable(pDrawable), pGC, depth,
+ dstX, dstY, dstWidth, dstHeight, leftPad, format, data);
+ }
+ else if (pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ fbPutImage(pDrawable, pGC, depth,
+ dstX, dstY, dstWidth, dstHeight, leftPad, format, data);
+ }
+ }
+
+ /*
+ * We are going to realize the operation
+ * on the real display. Let's check if
+ * the link is down.
+ */
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ goto nxagentPutImageEnd;
+ }
+
+ /*
+ * Mark the region as corrupted and skip the operation
+ * if we went out of bandwidth. The drawable will be
+ * synchronized at later time. Don't do that if the
+ * image is likely to be a shape or a clip mask, if we
+ * are here because we are actually synchronizing the
+ * drawable or if the drawable's corrupted region is
+ * over-age.
+ */
+
+ if (NXAGENT_SHOULD_DEFER_PUTIMAGE(pDrawable))
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP &&
+ pDrawable -> depth != 1 &&
+ nxagentOption(DeferLevel) >= 1)
+ {
+ /* -- changed by dimbor (small "bed-sheets" never need be prevented - always put) --*/
+ if (dstHeight > 16)
+ {
+ /* -------------------------------------------------------------------------------- */
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable at [%p] with drawable pixmap.\n", pRegion -> extents.x1,
+ pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2,
+ (void *) pDrawable);
+ #endif
+
+ nxagentMarkCorruptedRegion(pDrawable, pRegion);
+
+ goto nxagentPutImageEnd;
+ /* --- changed by dimbor ---*/
+ }
+ /* ------------------------- */
+ }
+
+ if (pDrawable -> type == DRAWABLE_WINDOW &&
+ nxagentOption(DeferLevel) >= 2)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable at [%p] with drawable window.\n", pRegion -> extents.x1,
+ pRegion -> extents.y1, pRegion -> extents.x2, pRegion -> extents.y2,
+ (void *) pDrawable);
+ #endif
+
+ nxagentMarkCorruptedRegion(pDrawable, pRegion);
+
+ goto nxagentPutImageEnd;
+ }
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentPutImage: Operation on drawable [%p] not skipped with nxagentSplitTrap [%d].\n",
+ (void *) pDrawable, nxagentSplitTrap);
+ }
+ #endif
+
+ /*
+ * Check whether we need to enclose the
+ * image in a split sequence.
+ */
+/*
+FIXME: Should we disable the split with link LAN?
+
+ split = (nxagentOption(Streaming) == 1 &&
+ nxagentOption(LinkType) != LINK_TYPE_NONE &&
+ nxagentOption(LinkType) != LINK_TYPE_LAN
+*/
+ split = (nxagentOption(Streaming) == 1 &&
+ nxagentOption(LinkType) != LINK_TYPE_NONE
+/*
+FIXME: Do we stream the images from GLX or Xv? If we do that,
+ we should also write on the frame buffer, including the
+ images put on windows, to be able to reconstruct the
+ region that is out of sync. Surely we should not try to
+ cache the GLX and Xv images in memory or save them in
+ the image cache on disk.
+*/
+/*
+FIXME: Temporarily stream the GLX data.
+
+ && nxagentGlxTrap == 0
+ && nxagentXvTrap == 0
+*/
+);
+
+ /*
+ * Never split images whose depth
+ * is less than 15.
+ */
+
+ if (split == 1 && (nxagentSplitTrap == 1 || depth < 15))
+ {
+ #ifdef TEST
+
+ if (nxagentSplitTrap == 1 ||
+ nxagentReconnectTrap == 1)
+ {
+ fprintf(stderr, "nxagentPutImage: Not splitting with reconnection [%d] trap [%d] "
+ "depth [%d].\n", nxagentSplitTrap, nxagentReconnectTrap, depth);
+ }
+
+ #endif
+
+ split = 0;
+ }
+ #ifdef TEST
+ else if (split == 1)
+ {
+ fprintf(stderr, "nxagentPutImage: Splitting with reconnection [%d] trap [%d] "
+ "depth [%d].\n", nxagentSplitTrap, nxagentReconnectTrap, depth);
+ }
+ #endif
+
+ #ifdef TEST
+
+ if (split == 1)
+ {
+ fprintf(stderr, "nxagentPutImage: Splitting the image with size [%d] "
+ "link [%d] GLX [%d] Xv [%d].\n", length, nxagentOption(LinkType),
+ nxagentGlxTrap, nxagentXvTrap);
+ }
+ else if (nxagentOption(LinkType) != LINK_TYPE_NONE)
+ {
+ fprintf(stderr, "nxagentPutImage: Not splitting the image with size [%d] "
+ "link [%d] GLX [%d] Xv [%d].\n", length, nxagentOption(LinkType),
+ nxagentGlxTrap, nxagentXvTrap);
+ }
+
+ #endif
+
+ /*
+ * If the image was originated by a GLX
+ * or Xvideo request, temporarily disable
+ * the use of the cache.
+ */
+
+ if (nxagentOption(LinkType) != LINK_TYPE_NONE &&
+ (nxagentGlxTrap == 1 || nxagentXvTrap == 1))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Disabling the use of the cache with GLX or Xvideo.\n");
+ #endif
+
+ NXSetCacheParameters(nxagentDisplay, 0, 1, 0, 0);
+
+ cache = 0;
+ }
+
+ /*
+ * Enclose the next messages in a split
+ * sequence. The proxy will tell us if
+ * the split took place.
+ */
+
+ if (split == 1)
+ {
+ /*
+ * If the drawable is already being split,
+ * expand the region. Currently drawables
+ * can't have more than a single split
+ * region.
+ */
+
+ if (nxagentSplitResource(pDrawable) != NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPutImage: WARNING! Expanding the region with drawable at [%p] streaming.\n",
+ (void *) pDrawable);
+ #endif
+/*
+FIXME: Should probably intersect the region with
+ the region being split to also invalidate
+ the commits.
+*/
+ nxagentMarkCorruptedRegion(pDrawable, pRegion);
+
+ goto nxagentPutImageEnd;
+ }
+ else
+ {
+ /*
+ * Assign a new resource to the drawable.
+ * Will also assign the GC to use for the
+ * operation.
+ */
+
+ resource = nxagentCreateSplit(pDrawable, &pGC);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Resource [%d] assigned to drawable at [%p].\n",
+ resource, (void *) pDrawable);
+ #endif
+ }
+
+ NXStartSplit(nxagentDisplay, resource, NXSplitModeDefault);
+ }
+
+ nxagentRealizeImage(pDrawable, pGC, depth, dstX, dstY,
+ dstWidth, dstHeight, leftPad, format, data);
+
+ if (split == 1)
+ {
+ NXEndSplit(nxagentDisplay, resource);
+
+ /*
+ * Now we need to check if all the messages went
+ * straight through the output stream or any of
+ * them required a split. If no split will take
+ * place, we will remove the association with the
+ * drawable and release the resource at the time
+ * we will handle the no-split event.
+ */
+
+ split = nxagentWaitSplitEvent(resource);
+
+ if (split == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Marking corrupted region [%d,%d,%d,%d] for drawable at [%p].\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2,
+ pRegion -> extents.y2, (void *) pDrawable);
+ #endif
+
+ /*
+ * Marking the corrupted region we will check
+ * if the region intersects the split region,
+ * therefore the split region must be added
+ * later.
+ */
+
+ nxagentMarkCorruptedRegion(pDrawable, pRegion);
+
+ /*
+ * Assign the region to the drawable.
+ */
+
+ nxagentRegionSplit(pDrawable, pRegion);
+
+ pRegion = NullRegion;
+ }
+ }
+
+ /*
+ * The split value could be changed by a
+ * no-split event in the block above, so
+ * here we have to check the value again.
+ */
+
+ if (split == 0)
+ {
+ if (nxagentDrawableStatus(pDrawable) == NotSynchronized)
+ {
+ /*
+ * We just covered the drawable with
+ * a solid image. We can consider the
+ * overlapping region as synchronized.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Marking synchronized region [%d,%d,%d,%d] for drawable at [%p].\n",
+ pRegion -> extents.x1, pRegion -> extents.y1, pRegion -> extents.x2,
+ pRegion -> extents.y2, (void *) pDrawable);
+ #endif
+
+ nxagentUnmarkCorruptedRegion(pDrawable, pRegion);
+ }
+ }
+
+nxagentPutImageEnd:
+
+ /*
+ * Check if we disabled caching.
+ */
+
+ if (cache == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutImage: Reenabling the use of the cache.\n");
+ #endif
+
+ NXSetCacheParameters(nxagentDisplay, 1, 1, 1, 1);
+ }
+
+ if (pRegion != NullRegion)
+ {
+ nxagentFreeRegion(pDrawable, pRegion);
+ }
+}
+
+void nxagentRealizeImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad,
+ int format, char *data)
+{
+ int length;
+
+ int bytesPerLine;
+ int numSubImages;
+ int totalHeight;
+
+ /*
+ * NXPutPackedImage is longer than PutPackedImage
+ * so that we subtract the bigger one to be sure.
+ */
+
+ const int subSize = (MAX_REQUEST_SIZE << 2) - sizeof(xNXPutPackedImageReq);
+
+ Visual *pVisual = NULL;
+
+ RegionPtr clipRegion = NullRegion;
+
+ XImage *image = NULL;
+
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRealizeImage: Returning on display error.\n");
+ #endif
+
+ goto nxagentRealizeImageEnd;
+ }
+
+ /*
+ * Get the visual according to the
+ * drawable and depth.
+ */
+
+ pVisual = nxagentImageVisual(pDrawable, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRealizeImage: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ /*
+ * Get bytes per line according to format.
+ */
+
+ bytesPerLine = nxagentImagePad(w, format, leftPad, depth);
+
+ if (nxagentOption(Shadow) == 1 && format == ZPixmap &&
+ (nxagentOption(XRatio) != DONT_SCALE ||
+ nxagentOption(YRatio) != DONT_SCALE) &&
+ pDrawable == (DrawablePtr) nxagentShadowPixmapPtr)
+ {
+ int scaledx;
+ int scaledy;
+
+ image = XCreateImage(nxagentDisplay, pVisual, depth, ZPixmap,
+ 0, data, w, h, BitmapPad(nxagentDisplay), bytesPerLine);
+
+ if (image != NULL)
+ {
+ image -> byte_order = IMAGE_BYTE_ORDER;
+
+ image -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ nxagentScaleImage(x, y, nxagentOption(XRatio), nxagentOption(YRatio),
+ &image, &scaledx, &scaledy);
+
+ x = scaledx;
+ y = scaledy;
+
+ w = image -> width;
+ h = image -> height;
+
+ data = image -> data;
+
+ /*
+ * Width of image has changed.
+ */
+
+ bytesPerLine = nxagentImagePad(w, format, leftPad, depth);
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "nxagentRealizeImage: Failed to create XImage for scaling.\n");
+ }
+ #endif
+ }
+
+ if (w == 0 || h == 0)
+ {
+ goto nxagentRealizeImageEnd;
+ }
+
+ totalHeight = h;
+
+ length = bytesPerLine * h;
+
+ h = (subSize < length ? subSize : length) / bytesPerLine;
+
+ numSubImages = totalHeight / h + 1;
+
+ while (numSubImages > 0)
+ {
+ if (pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ clipRegion = nxagentCreateRegion(pDrawable, pGC, x, y, w, h);
+ }
+
+ if (clipRegion == NullRegion || RegionNil(clipRegion) == 0)
+ {
+ nxagentPutSubImage(pDrawable, pGC, depth, x, y, w, h,
+ leftPad, format, data, pVisual);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentRealizeImage: Skipping the put sub image with geometry "
+ "[%d,%d,%d,%d] on hidden window at [%p].\n", x, y, w, h, (void *) pDrawable);
+ }
+ #endif
+
+ if (clipRegion != NullRegion)
+ {
+ nxagentFreeRegion(pDrawable, clipRegion);
+ }
+
+ y += h;
+
+ data += h * bytesPerLine;
+
+ if (--numSubImages == 1)
+ {
+ h = totalHeight % h;
+
+ if (h == 0)
+ {
+ break;
+ }
+ }
+ }
+
+nxagentRealizeImageEnd:
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+}
+
+void nxagentPutSubImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *data, Visual *pVisual)
+{
+ NXPackedImage *packedImage = NULL;
+ XImage *plainImage = NULL;
+ unsigned char *packedChecksum = NULL;
+
+ unsigned int packMethod = nxagentPackMethod;
+ unsigned int packQuality = nxagentPackQuality;
+
+ ClientPtr client;
+
+ int lossless = 0;
+ int clean = 0;
+ int pack = 0;
+
+ /*
+ * XCreateImage is the place where the leftPad should be passed.
+ * The image data is received from our client unmodified. In
+ * theory what we would need to do is just creating an appropri-
+ * ate XImage structure based on the incoming data and let Xlib
+ * do the rest. Probably we don't have to pass leftPad again in
+ * the src_x of XPutImage otherwise the src_x would make Xlib
+ * to take into account the xoffset field twice. Unfortunately
+ * passing the leftPad doesn't work.
+ *
+ * plainImage = XCreateImage(nxagentDisplay, pVisual,
+ * depth, format, leftPad, data,
+ * w, h, BitmapPad(nxagentDisplay),
+ * nxagentImagePad(w, format, leftPad, depth));
+ */
+
+ if ((plainImage = XCreateImage(nxagentDisplay, pVisual,
+ depth, format, leftPad, data,
+ w, h, BitmapPad(nxagentDisplay),
+ nxagentImagePad(w, format, leftPad, depth))) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPutSubImage: WARNING! Failed to create image.\n");
+ #endif
+
+ goto nxagentPutSubImageEnd;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Handling image with geometry [%d,%d] depth [%d].\n",
+ w, h, depth);
+
+ fprintf(stderr, "nxagentPutSubImage: Default pack method is [%d] quality is [%d].\n",
+ packMethod, packQuality);
+ #endif
+
+/*
+FIXME: Should use an unpack resource here.
+*/
+ client = requestingClient;
+
+ if (client == NULL)
+ {
+ client = serverClient;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: WARNING! Using the server client with index [%d].\n",
+ client -> index);
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Server order is [%d] client order is [%d].\n",
+ nxagentServerOrder(), nxagentClientOrder(client));
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Display image order is [%d] bitmap order is [%d].\n",
+ ImageByteOrder(nxagentDisplay), nxagentBitmapBitOrder(nxagentDisplay));
+ #endif
+
+ /*
+ * We got the image data from the X client or
+ * from the frame-buffer with our own endianess.
+ * Byte swap the image data if the display has
+ * a different endianess than our own.
+ */
+
+ if (nxagentImageNormalize(plainImage) != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: WARNING! Reformatted the image with remote order [%d/%d].\n",
+ plainImage -> byte_order, plainImage -> bitmap_bit_order);
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Image has visual with RGB color masks [%0lx][%0lx][%0lx].\n",
+ pVisual -> red_mask, pVisual -> green_mask, pVisual -> blue_mask);
+ #endif
+
+ /*
+ * Check if the user requested to pack the
+ * image but don't pack it if we are not
+ * connected to a proxy or if the depth is
+ * less than 15 bpp.
+ */
+
+ pack = (nxagentOption(LinkType) != LINK_TYPE_NONE &&
+ packMethod != PACK_NONE && depth > 8 && format == ZPixmap);
+
+ lossless = (packMethod == nxagentPackLossless);
+
+ if (pack == 1 && lossless == 0)
+ {
+ /*
+ * Force the image to be sent as a plain
+ * bitmap if we don't have any lossless
+ * encoder available.
+ */
+
+ if (w <= IMAGE_PACK_WIDTH || h <= IMAGE_PACK_HEIGHT ||
+ nxagentImageLength(w, h, format, leftPad, depth) <=
+ IMAGE_PACK_LENGTH || nxagentLosslessTrap == 1)
+ {
+ if (nxagentPackLossless == PACK_NONE)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Disabling pack with lossless method [%d] "
+ "trap [%d] size [%d].\n", nxagentPackLossless, nxagentLosslessTrap,
+ nxagentImageLength(w, h, format, leftPad, depth));
+ #endif
+
+ pack = 0;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Lossless encoder with geometry [%d,%d] "
+ "trap [%d] size [%d].\n", w, h, nxagentLosslessTrap,
+ nxagentImageLength(w, h, format, leftPad, depth));
+ #endif
+
+ packMethod = nxagentPackLossless;
+
+ lossless = 1;
+ }
+ }
+ }
+
+ /*
+ * Do we still want to pack the image?
+ */
+
+ if (pack == 1)
+ {
+ /*
+ * Set the geometry and alpha channel
+ * to be used for the unpacked image.
+ */
+
+ if (nxagentUnpackVisualId[client -> index] != pVisual -> visualid)
+ {
+ nxagentUnpackVisualId[client -> index] = pVisual -> visualid;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Sending new geometry for client [%d].\n",
+ client -> index);
+ #endif
+
+ NXSetUnpackGeometry(nxagentDisplay, client -> index, pVisual);
+ }
+
+ /*
+ * Check if the image is supposed to carry
+ * the alpha data in the fourth byte and,
+ * if so, send the alpha channel using the
+ * specific encoding.
+ */
+
+ if (plainImage -> depth == 32)
+ {
+ nxagentSetUnpackAlpha(pDrawable, plainImage, client);
+ }
+
+ /*
+ * If the image doesn't come from the XVideo or the
+ * GLX extension try to locate it in the cache. The
+ * case of the lossless trap is also special, as we
+ * want to eventually encode the image again using
+ * a lossless compression.
+ */
+/*
+FIXME: Should try to locate the image anyway, if the lossless
+ trap is set, and if the image was encoded by a lossy
+ compressor, roll back the changes and encode the image
+ again using the preferred method.
+*/
+ if (nxagentNeedCache(plainImage, packMethod) &&
+ nxagentGlxTrap == 0 && nxagentXvTrap == 0 &&
+ nxagentLosslessTrap == 0 && NXImageCacheSize > 0)
+ {
+ /*
+ * Be sure that the padding bits are
+ * cleaned before calculating the MD5
+ * checksum.
+ */
+/*
+FIXME: There should be a callback registered by the agent that
+ provides a statistics report, in text format, telling
+ for example how many images were searched in the cache,
+ how many were found, how many drawables are to be synch-
+ ronized, etc. This statistics report would be included
+ by the proxy in its stat output.
+*/
+ clean = 1;
+
+ NXCleanImage(plainImage);
+
+ /*
+ * Will return a pointer to the image and checksum
+ * taken from the cache, if found. If the image is
+ * not found, the function returns a null image and
+ * a pointer to the calculated checksum. It is up
+ * to the application to free the memory. We will
+ * use the checksum to add the image in the cache.
+ */
+
+ packedImage = NXCacheFindImage(plainImage, &packMethod, &packedChecksum);
+
+ nxagentImageStatistics.partialLookups++;
+ nxagentImageStatistics.totalLookups++;
+
+ if (packedImage != NULL)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Matched image of geometry [%d,%d] data size [%d] in cache.\n",
+ w, h, packedImage -> xoffset);
+ #endif
+
+ NXPutPackedImage(nxagentDisplay, client -> index, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), packedImage, packMethod, depth,
+ 0, 0, x, y, w, h);
+
+ nxagentImageStatistics.partialMatches++;
+ nxagentImageStatistics.totalMatches++;
+
+ packedChecksum = NULL;
+ packedImage = NULL;
+
+ goto nxagentPutSubImageEnd;
+ }
+ #ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "nxagentPutSubImage: WARNING! Missed image of geometry [%d,%d] in cache.\n",
+ w, h);
+ }
+ #endif
+ }
+
+ /*
+ * If a specific encoder was not mandated,
+ * try to guess if a lossless encoder will
+ * compress better.
+ */
+
+ if (lossless == 0 && nxagentOption(Adaptive) == 1)
+ {
+ int ratio = nxagentUniquePixels(plainImage);
+
+ if (ratio <= IMAGE_UNIQUE_RATIO)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Lossless encoder with geometry [%d,%d] ratio [%d%%].\n",
+ w, h, ratio);
+ #endif
+
+ packMethod = nxagentPackLossless;
+
+ lossless = 1;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentPutSubImage: Default encoder with geometry [%d,%d] ratio [%d%%].\n",
+ w, h, ratio);
+ }
+ #endif
+ }
+
+ /*
+ * Encode the image using the selected
+ * pack method.
+ */
+
+ if (packMethod == PACK_RLE_16M_COLORS ||
+ packMethod == PACK_RGB_16M_COLORS ||
+ packMethod == PACK_BITMAP_16M_COLORS)
+ {
+ /*
+ * Cleanup the image if we didn't do that yet.
+ * We assume that the JPEG and PNG compression
+ * methods will actually ignore the padding
+ * bytes. In other words, bitmap images prod-
+ * ucing the same visual output should produce
+ * compressed images that are bitwise the same
+ * regardless the padding bits.
+ */
+
+ if (clean == 0)
+ {
+ if (nxagentNeedClean(plainImage, packMethod) == 1)
+ {
+ clean = 1;
+
+ NXCleanImage(plainImage);
+ }
+ }
+
+ switch (packMethod)
+ {
+ /*
+ * If nothing is done by the bitmap encoder,
+ * it saves an allocation and a memory copy
+ * by setting the data field of the packed
+ * image to the original data. We need to
+ * check this at the time we will free the
+ * packed image.
+ */
+
+ case PACK_BITMAP_16M_COLORS:
+ {
+ packedImage = NXEncodeBitmap(plainImage, packMethod, packQuality);
+
+ break;
+ }
+ case PACK_RGB_16M_COLORS:
+ {
+ packedImage = NXEncodeRgb(plainImage, packMethod, packQuality);
+
+ break;
+ }
+ default:
+ {
+ packedImage = NXEncodeRle(plainImage, packMethod, packQuality);
+
+ break;
+ }
+ }
+ }
+ else if (packMethod >= PACK_JPEG_8_COLORS &&
+ packMethod <= PACK_JPEG_16M_COLORS)
+ {
+ packedImage = NXEncodeJpeg(plainImage, packMethod, packQuality);
+ }
+ else if (packMethod >= PACK_PNG_8_COLORS &&
+ packMethod <= PACK_PNG_16M_COLORS)
+ {
+ packedImage = NXEncodePng(plainImage, packMethod, packQuality);
+ }
+ else if (packMethod != PACK_NONE)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPutSubImage: WARNING! Ignoring deprecated pack method [%d].\n",
+ packMethod);
+ #endif
+
+ packMethod = PACK_NONE;
+ }
+ }
+
+ /*
+ * If we didn't produce a valid packed
+ * image, send the image as a X bitmap.
+ */
+
+ if (packedImage != NULL)
+ {
+ nxagentImageStatistics.partialEncoded++;
+ nxagentImageStatistics.totalEncoded++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Using packed image with method [%d] quality [%d] "
+ "geometry [%d,%d] data size [%d].\n", packMethod, packQuality,
+ w, h, packedImage -> xoffset);
+ #endif
+
+ NXPutPackedImage(nxagentDisplay, client -> index, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), packedImage, packMethod, depth,
+ 0, 0, x, y, w, h);
+
+ /*
+ * Add the image only if we have a valid
+ * checksum. This is the case only if we
+ * originally tried to find the image in
+ * cache.
+ */
+
+ if (NXImageCacheSize > 0 && packedChecksum != NULL)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Adding image with geometry [%d,%d] data size [%d] "
+ "to the cache.\n", w, h, packedImage -> xoffset);
+ #endif
+
+ /*
+ * Check if both the plain and the packed
+ * image point to the same data. In this
+ * case we need a copy.
+ */
+
+ if (packedImage -> data == plainImage -> data &&
+ nxagentImageCopy(plainImage, packedImage) == NULL)
+ {
+ goto nxagentPutSubImageEnd;
+ }
+
+ NXCacheAddImage(packedImage, packMethod, packedChecksum);
+
+ nxagentImageStatistics.partialAdded++;
+ nxagentImageStatistics.totalAdded++;
+
+ packedChecksum = NULL;
+ packedImage = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * Clean the image to help the proxy to match
+ * the checksum in its cache. Do that only if
+ * the differential compression is enabled and
+ * if the image is not supposed to carry the
+ * alpha data in the fourth byte of the pixel.
+ */
+/*
+FIXME: If we failed to encode the image by any of the available
+ methods, for example if we couldn't allocate memory, we
+ may need to ripristinate the alpha channel, that in the
+ meanwhile was sent in the unpack alpha message. This can
+ be done here, if the clean flag is true and we are going
+ to send a plain image.
+*/
+ if (clean == 0)
+ {
+ clean = (nxagentOption(LinkType) != LINK_TYPE_NONE &&
+ nxagentOption(LinkType) != LINK_TYPE_LAN && depth != 32);
+
+ if (clean == 1)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Cleaning the image with link type [%d] and depth [%d].\n",
+ nxagentOption(LinkType), depth);
+ #endif
+
+ NXCleanImage(plainImage);
+ }
+ #ifdef DEBUG
+ else
+ {
+ fprintf(stderr, "nxagentPutSubImage: Not cleaning the image with link type [%d] and depth [%d].\n",
+ nxagentOption(LinkType), depth);
+ }
+ #endif
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPutSubImage: Calling XPutImage with geometry [%d,%d] and data size [%d].\n",
+ w, h, plainImage -> bytes_per_line * plainImage -> height);
+ #endif
+
+ /*
+ * Passing the leftPad value in src_x doesn't work.
+ *
+ * XPutImage(nxagentDisplay, nxagentDrawable(pDrawable),
+ * nxagentGC(pGC), plainImage, leftPad, 0, x, y, w, h);
+ */
+
+ XPutImage(nxagentDisplay, nxagentDrawable(pDrawable),
+ nxagentGC(pGC), plainImage, 0, 0, x, y, w, h);
+ }
+
+nxagentPutSubImageEnd:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPutSubImage: Performed [%.0f] lookups in the cache with [%.0f] matches.\n",
+ nxagentImageStatistics.totalLookups, nxagentImageStatistics.totalMatches);
+
+ fprintf(stderr, "nxagentPutSubImage: Encoded [%.0f] images with [%.0f] added to the cache.\n",
+ nxagentImageStatistics.totalEncoded, nxagentImageStatistics.totalAdded);
+ #endif
+
+ if (packedChecksum != NULL)
+ {
+ free(packedChecksum);
+ }
+
+ if (packedImage != NULL)
+ {
+ if (packedImage -> data != NULL &&
+ packedImage -> data != plainImage -> data)
+ {
+ free(packedImage -> data);
+ }
+
+ free(packedImage);
+ }
+
+ free(plainImage);
+}
+
+void nxagentGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *data)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetImage: Called with drawable at [%p] geometry [%d,%d,%d,%d].\n",
+ (void *) pDrawable, x, y, w, h);
+
+ fprintf(stderr, "nxagentGetImage: Format is [%d] plane mask is [%lx].\n",
+ format, planeMask);
+ #endif
+
+ if ((pDrawable)->type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGetImage: Going to get image from virtual pixmap at [%p].\n",
+ (void *) nxagentVirtualDrawable(pDrawable));
+ #endif
+
+ fbGetImage(nxagentVirtualDrawable(pDrawable), x, y, w, h, format, planeMask, data);
+ }
+ else
+ {
+ fbGetImage(pDrawable, x, y, w, h, format, planeMask, data);
+ }
+}
+
+/*
+ * We have to reset the visual cache before
+ * connecting to another display, so that a
+ * new unpack geometry can be communicated
+ * to the new proxy.
+ */
+
+void nxagentResetVisualCache()
+{
+ int i;
+
+ for (i = 0; i < MAX_CONNECTIONS; i++)
+ {
+ nxagentUnpackVisualId[i] = None;
+ }
+}
+
+void nxagentResetAlphaCache()
+{
+ int i;
+
+ for (i = 0; i < MAX_CONNECTIONS; i++)
+ {
+ if (nxagentUnpackAlpha[i])
+ {
+ free(nxagentUnpackAlpha[i] -> data);
+
+ free(nxagentUnpackAlpha[i]);
+
+ nxagentUnpackAlpha[i] = NULL;
+ }
+ }
+}
+
+int nxagentScaleImage(int x, int y, unsigned xRatio, unsigned yRatio,
+ XImage **pImage, int *scaledx, int *scaledy)
+{
+ int x1;
+ int x2;
+ int y1;
+ int y2;
+
+ int xx1;
+ int xx2;
+ int yy1;
+ int yy2;
+
+ int newWidth;
+ int newHeight;
+
+ int i;
+ int j;
+ int k;
+ int l;
+
+ unsigned long val;
+
+ XImage *newImage;
+ XImage *image = *pImage;
+
+ #ifdef FAST_GET_PUT_PIXEL
+
+ register char *srcPixel;
+ register char *dstPixel;
+
+ int i;
+
+ #endif
+
+ if (image == NULL)
+ {
+ return 0;
+ }
+
+ x1 = (xRatio * x) >> PRECISION;
+ x2 = (xRatio * (x + image -> width)) >> PRECISION;
+
+ y1 = (yRatio * y) >> PRECISION;
+ y2 = (yRatio * (y + image -> height)) >> PRECISION;
+
+ newWidth = x2 - x1;
+ newHeight = y2 - y1;
+
+ newImage = XCreateImage(nxagentDisplay, NULL, image -> depth, image -> format, 0, NULL,
+ newWidth, newHeight, BitmapPad(nxagentDisplay),
+ PixmapBytePad(newWidth, image -> depth));
+
+ if (newImage == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentScaleImage: PANIC! Failed to create the target image.\n");
+ #endif
+
+ return 0;
+ }
+
+ newImage -> red_mask = image -> red_mask;
+ newImage -> green_mask = image -> green_mask;
+ newImage -> blue_mask = image -> blue_mask;
+
+ newImage -> byte_order = IMAGE_BYTE_ORDER;
+ newImage -> bitmap_bit_order = BITMAP_BIT_ORDER;
+
+ newImage -> data = Xmalloc(newImage -> bytes_per_line * newHeight);
+
+ if (newImage -> data == NULL)
+ {
+ free(newImage);
+
+ #ifdef PANIC
+ fprintf(stderr, "nxagentScaleImage: PANIC! Failed to create the target image data.\n");
+ #endif
+
+ return 0;
+ }
+
+ newImage -> width = newWidth;
+ newImage -> height = newHeight;
+
+ for (j = y; j < y + image -> height; j++)
+ {
+ yy1 = (yRatio * j) >> PRECISION;
+ yy2 = (yRatio * (j + 1)) >> PRECISION;
+
+ for (i = x; i < x + image -> width; i++)
+ {
+ #ifndef FAST_GET_PUT_PIXEL
+
+ val = XGetPixel(image, i - x, j - y);
+
+ #else
+
+ srcPixel = &image -> data[(j * image -> bytes_per_line) +
+ ((i * image -> bits_per_pixel) >> 3)];
+
+ dstPixel = (char *) &val;
+
+ val = 0;
+
+ for (i = (image -> bits_per_pixel + 7) >> 3; --i >= 0; )
+ {
+ *dstPixel++ = *srcPixel++;
+ }
+
+ #endif
+
+ xx1 = (xRatio * i) >> PRECISION;
+ xx2 = (xRatio * (i + 1)) >> PRECISION;
+
+ for (l = yy1; l < yy2; l++)
+ {
+ for (k = xx1; k < xx2; k++)
+ {
+ #ifndef FAST_GET_PUT_PIXEL
+
+ XPutPixel(newImage, k - x1, l - y1, val);
+
+ #else
+
+ dstPixel = &newImage -> data[((l - y1) * newImage -> bytes_per_line) +
+ (((k - x1) * newImage -> bits_per_pixel) >> 3)];
+
+ srcPixel = (char *) &val;
+
+ for (i = (newImage -> bits_per_pixel + 7) >> 3; --i >= 0; )
+ {
+ *dstPixel++ = *srcPixel++;
+ }
+
+ #endif
+ }
+ }
+ }
+ }
+
+ if (image -> obdata != NULL)
+ {
+ free((char *) image -> obdata);
+ }
+
+ free((char *) image);
+
+ *pImage = newImage;
+
+ *scaledx = x1;
+ *scaledy = y1;
+
+ return 1;
+}
+
+char *nxagentAllocateImageData(int width, int height, int depth, int *length, int *format)
+{
+ char *data;
+
+ int leftPad;
+
+ leftPad = 0;
+
+ *format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ *length = nxagentImageLength(width, height, *format, leftPad, depth);
+
+ data = NULL;
+
+ if ((data = malloc(*length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentAllocateImageData: WARNING! Failed to allocate [%d] bytes of memory.\n", *length);
+ #endif
+ }
+
+ return data;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Image.h b/nx-X11/programs/Xserver/hw/nxagent/Image.h
new file mode 100644
index 000000000..771c0dbe1
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Image.h
@@ -0,0 +1,116 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Image_H__
+#define __Image_H__
+
+/*
+ * Graphic operations.
+ */
+
+void nxagentPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int dstX, int dstY, int dstWidth, int dstHeight,
+ int leftPad, int format, char *data);
+
+void nxagentRealizeImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad,
+ int format, char *data);
+
+void nxagentPutSubImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *data, Visual *pVisual);
+
+void nxagentGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *data);
+
+/*
+ * Pack and split parameters we get
+ * from the NX transport.
+ */
+
+extern int nxagentPackLossless;
+extern int nxagentPackMethod;
+extern int nxagentPackQuality;
+extern int nxagentSplitThreshold;
+
+/*
+ * Set if images can use the alpha
+ * channel and if the alpha channel
+ * can be sent in compressed form.
+ */
+
+extern int nxagentAlphaEnabled;
+extern int nxagentAlphaCompat;
+
+/*
+ * Reset the visual and alpha cache
+ * before closing the screen or con-
+ * necting to a different display.
+ */
+
+void nxagentResetVisualCache(void);
+void nxagentResetAlphaCache(void);
+
+/*
+ * Always use the default visual for the
+ * image related functions.
+ */
+
+#define nxagentImageVisual(pDrawable, depth) \
+ ((depth) == 32 ? &nxagentAlphaVisual : \
+ nxagentDefaultVisual(((pDrawable) -> pScreen)))
+
+/*
+ * Byte swap the image if the display
+ * uses a different endianess.
+ */
+
+#define nxagentImageNormalize(image) \
+ ((image) -> byte_order != IMAGE_BYTE_ORDER || \
+ (image) -> bitmap_bit_order != BITMAP_BIT_ORDER ? \
+ nxagentImageReformat((image) -> data, (image) -> bytes_per_line * \
+ (image) -> height * ((image) -> format == XYPixmap ? (image) -> depth : 1), \
+ ((image) -> format == ZPixmap ? \
+ BitsPerPixel((image) -> depth) : 1), \
+ (image) -> byte_order) : 0)
+
+/*
+ * Other image related functions.
+ */
+
+int nxagentImageLength(int width, int height, int format, int leftPad, int depth);
+
+int nxagentImagePad(int width, int format, int leftPad, int depth);
+
+int nxagentImageReformat(char *base, int nbytes, int bpp, int order);
+
+void nxagentImageStatisticsHandler(char **buffer, int type);
+
+int nxagentScaleImage(int x, int y, unsigned xRatio, unsigned yRatio, XImage **pImage, int *scaledx, int *scaledy);
+
+char *nxagentAllocateImageData(int width, int height, int depth, int *length, int *format);
+
+#endif /* __Image_H__ */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Imakefile b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
new file mode 100644
index 000000000..a1b059cae
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Imakefile
@@ -0,0 +1,270 @@
+#include <Server.tmpl>
+
+
+NULL =
+
+SUBDIRS = compext \
+ $(NULL)
+
+SRCS = \
+ NXwindow.c \
+ NXevents.c \
+ NXproperty.c \
+ NXdixfonts.c \
+ NXglyphcurs.c \
+ NXdispatch.c \
+ NXrender.c \
+ NXglyph.c \
+ NXpicture.c \
+ NXextension.c \
+ NXshm.c \
+ NXglxext.c \
+ NXxvdisp.c \
+ NXmiexpose.c \
+ NXresource.c \
+ NXdamage.c \
+ NXmitrap.c \
+ Args.c \
+ Binder.c \
+ BitmapUtils.c \
+ Colormap.c \
+ Cursor.c \
+ Dialog.c \
+ Display.c \
+ Events.c \
+ Font.c \
+ GC.c \
+ GCOps.c \
+ Millis.c \
+ Handlers.c \
+ Init.c \
+ Keyboard.c \
+ Keystroke.c \
+ Pointer.c \
+ Screen.c \
+ TestExt.c \
+ Visual.c \
+ Drawable.c \
+ Window.c \
+ Pixmap.c \
+ Render.c \
+ Client.c \
+ Rootless.c \
+ Extensions.c \
+ Options.c \
+ Clipboard.c \
+ Splash.c \
+ Split.c \
+ Holder.c \
+ Reconnect.c \
+ Error.c \
+ Atoms.c \
+ Trap.c \
+ Image.c \
+ Composite.c \
+ Pixels.c \
+ stubs.c \
+ xpstubs.c \
+ miinitext.c \
+ $(NULL)
+
+OBJS = \
+ NXwindow.o \
+ NXevents.o \
+ NXproperty.o \
+ NXdixfonts.o \
+ NXglyphcurs.o \
+ NXdispatch.o \
+ NXrender.o \
+ NXglyph.o \
+ NXpicture.o \
+ NXextension.o \
+ NXshm.o \
+ NXglxext.o \
+ NXxvdisp.o \
+ NXmiexpose.o \
+ NXresource.o \
+ NXdamage.o \
+ NXmitrap.o \
+ Args.o \
+ Binder.o \
+ BitmapUtils.o \
+ Colormap.o \
+ Cursor.o \
+ Dialog.o \
+ Display.o \
+ Events.o \
+ Font.o \
+ GC.o \
+ GCOps.o \
+ Millis.o \
+ Handlers.o \
+ Init.o \
+ Keyboard.o \
+ Keystroke.o \
+ Pointer.o \
+ Screen.o \
+ TestExt.o \
+ Visual.o \
+ Drawable.o \
+ Window.o \
+ Pixmap.o \
+ Render.o \
+ Client.o \
+ Rootless.o \
+ Extensions.o \
+ Options.o \
+ Clipboard.o \
+ Splash.o \
+ Split.o \
+ Holder.o \
+ Reconnect.o \
+ Error.o \
+ Atoms.o \
+ Trap.o \
+ Image.o \
+ Composite.o \
+ Pixels.o \
+ stubs.o \
+ xpstubs.o \
+ miinitext.o \
+ $(NULL)
+
+VFBINCLUDES = \
+ -I../../fb \
+ -I../../mfb \
+ -I../../render \
+ $(NULL)
+
+INCLUDES = \
+ -I. \
+ -I../../../../extras/Mesa/include \
+ -I$(XBUILDINCDIR) \
+ -I../../mi \
+ -I../../include \
+ -I../../os \
+ -I../../miext/damage \
+ -I../../miext/cw \
+ -I../../GL/glx \
+ -I../../GL/include \
+ -I../../../../lib/GL/include \
+ -I../../Xext \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+ $(VFBINCLUDES) \
+ `pkg-config --cflags-only-I libxml-2.0` \
+ `pkg-config --cflags-only-I pixman-1` \
+ $(NULL)
+#ifdef SunArchitecture
+INCLUDES = \
+ -I. \
+ -I../../../../extras/Mesa/include \
+ -I$(XBUILDINCDIR) \
+ -I/usr/sfw/include \
+ -I../../mi \
+ -I../../include \
+ -I../../os \
+ -I../../GL/glx \
+ -I../../GL/include \
+ -I../../../../lib/GL/include \
+ -I../../Xext \
+ -I../../miext/damage \
+ -I../../miext/cw \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+ $(VFBINCLUDES) \
+ `pkg-config --cflags-only-I libxml-2.0` \
+ `pkg-config --cflags-only-I pixman-1` \
+ `pkg-config --cflags-only-I zlib` \
+ `pkg-config --cflags-only-I libpng` \
+ $(NULL)
+#else
+#ifdef cygwinArchitecture
+INCLUDES = \
+ -I. -I$(XBUILDINCDIR) \
+ -I../../mi \
+ -I../../include \
+ -I../../os \
+ -I../../GL/glx \
+ -I../../GL/include \
+ -I../../../../lib/GL/include \
+ -I../../Xext \
+ -I../../miext/damage \
+ -I../../miext/cw \
+ -I../../../../../nxcomp \
+ -I../../../../../nxcompshad \
+ -I../../../../extras/Mesa/include \
+ -I$(EXTINCSRC) -I$(XINCLUDESRC) \
+ $(VFBINCLUDES) \
+ `pkg-config --cflags-only-I libxml-2.0` \
+ `pkg-config --cflags-only-I pixman-1` \
+ `pkg-config --cflags-only-I zlib` \
+ `pkg-config --cflags-only-I libpng` \
+ $(NULL)
+#endif
+#endif
+
+### NXAGENT Defines:
+#
+# NXAGENT_FONTCACHE_SIZE Number of cache slots
+# NXAGENT_SHAPE Old shape code
+# NXAGENT_GLYPHCACHE
+# NXAGENT_GLYPHCACHE_SIZE Slots for glyph cache
+# NXAGENT_SHAPE2 New shape code
+# NXAGENT_FIXKEYS Force the release of pressed key when loosing focus
+# NXAGENT_EXPOSURES Manage expose events
+# NXAGENT_CLIPBOARD Enables clipboard cut and paste function between X servers.
+# NXAGENT_FONTEXCLUDE Exclude some specific font names (only "-ult1mo" at this moment).
+# NXAGENT FULLSCREEN Fullscreen mode
+# NXAGENT_RANDR_MODE_PREFIX Use prefixed (i.e., nx_<x>x<y>) RandR modes
+# NXAGENT_RANDR_XINERAMA_CLIPPING cut off invisible window parts in xinerama mode (you probably do not want this)
+
+#if nxVersion
+NX_DEFINES = \
+ -DNX_VERSION_CURRENT="$(NX_VERSION_CURRENT)" \
+ -DNX_VERSION_CURRENT_STRING="\"$(NX_VERSION_CURRENT_STRING)\"" \
+ $(NULL)
+#endif
+
+DEFINES = \
+ -g $(OS_DEFINES) $(EXT_DEFINES) $(NX_DEFINES) \
+ -UXF86VIDMODE -UXFreeXDGA -UXF86MISC -UXF86DRI \
+ -DNXAGENT_SERVER \
+ -DNXAGENT_CONSTRAINCURSOR \
+ -DNXAGENT_FONTCACHE_SIZE=50 \
+ -DNXAGENT_GLYPHCACHE -DNXAGENT_GLYPHCACHE_SIZE=50 \
+ -DNXAGENT_SHAPE2 \
+ -DNXAGENT_FIXKEYS \
+ -DNXAGENT_CLIPBOARD \
+ -DNXAGENT_EXPOSURES \
+ -DNXAGENT_FONTEXCLUDE \
+ -DNXAGENT_PACKEDIMAGES \
+ -DNXAGENT_VISIBILITY \
+ -DNXAGENT_WAKEUP=1000 \
+ -DNXAGENT_ONSTART \
+ -DNXAGENT_SPLASH \
+ -DNXAGENT_ARTSD \
+ -DNXAGENT_RANDR_MODE_PREFIX \
+ -UNX_DEBUG_INPUT \
+ -DRANDR_10_INTERFACE=1 \
+ -DRANDR_12_INTERFACE=1 \
+ -DRANDR_13_INTERFACE=1 \
+ -DRANDR_14_INTERFACE=1 \
+ -DRANDR_15_INTERFACE=1 \
+ -DPANORAMIX \
+ -UDEBUG_TREE \
+ $(NULL)
+
+all:: $(OBJS)
+
+LinkSourceFile(stubs.c,$(SERVERSRC)/Xi)
+LinkSourceFile(xpstubs.c,$(SERVERSRC)/dix)
+LinkSourceFile(miinitext.c,$(SERVERSRC)/mi)
+SpecialCObjectRule(miinitext,$(ICONFIGFILES), $(_NOOP_))
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(nxagent,$(OBJS))
+
+DependTarget()
+
+#define IHaveSubdirs
+MakeSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Init.c b/nx-X11/programs/Xserver/hw/nxagent/Init.c
new file mode 100644
index 000000000..a35e3d5a8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Init.c
@@ -0,0 +1,581 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "X.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mi.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Pointer.h"
+#include "Keyboard.h"
+#include "Handlers.h"
+#include "Events.h"
+#include "Init.h"
+#include "Args.h"
+#include "Client.h"
+#include "Options.h"
+#include "Drawable.h"
+#include "Pixmaps.h"
+#include "GCs.h"
+#include "Font.h"
+#include "Millis.h"
+#include "Error.h"
+#include "Keystroke.h"
+
+#include <nx/NX.h>
+#include "compext/Compext.h"
+#include "Reconnect.h"
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+#define NXAGENT_VERSION NX_VERSION_CURRENT
+#define NXAGENT_VERSION_STRING NX_VERSION_CURRENT_STRING
+
+/*
+ * ProcVector array defined in tables.c.
+ */
+
+extern int (*ProcVector[256])(ClientPtr);
+
+/*
+ * From the fb code.
+ */
+
+extern int fbGCPrivateIndex;
+
+/*
+ * Stubs for the DPMS extension.
+ */
+
+#ifdef DPMSExtension
+
+void DPMSSet(int level);
+int DPMSGet(int *level);
+Bool DPMSSupported(void);
+
+#endif
+
+/*
+ * Our error logging function.
+ */
+
+void OsVendorVErrorFFunction(const char *f, va_list args);
+
+/*
+ * True if this is a fatal error.
+ */
+
+extern int OsVendorVErrorFFatal;
+
+/*
+ * Redirect the error output to a
+ * different file
+ */
+
+extern void (*OsVendorStartRedirectErrorFProc)();
+extern void (*OsVendorEndRedirectErrorFProc)();
+
+extern void SetVendorRelease(int release);
+
+void OsVendorStartRedirectErrorFFunction();
+void OsVendorEndRedirectErrorFFunction();
+
+/*
+ * Called by InitGlobals() in the
+ * new X server tree.
+ */
+
+
+static void nxagentGrabServerCallback(CallbackListPtr *callbacks, void *data,
+ void *args);
+
+void ddxInitGlobals(void)
+{
+ /*
+ * Install our error logging function.
+ */
+
+ OsVendorVErrorFProc = OsVendorVErrorFFunction;
+
+ OsVendorStartRedirectErrorFProc = OsVendorStartRedirectErrorFFunction;
+ OsVendorEndRedirectErrorFProc = OsVendorEndRedirectErrorFFunction;
+}
+
+/*
+ * Set if the remote display supports
+ * backing store.
+ */
+/*
+FIXME: These, if not removed, should at least
+ be moved to Display.h and Display.c.
+*/
+int nxagentBackingStore;
+int nxagentSaveUnder;
+
+/*
+ * This is true at startup and set to the value of
+ * nxagentFullGeneration at the end of InitInput.
+ *
+ * InitOutput
+ * nxagentOpenDisplay (if nxagentDoFullGeneration)
+ * nxagentCloseDisplay (if (nxagentDoFullGeneration && nxagentDisplay))
+ * nxagentFree*
+ * nxagentListRemoteFonts
+ * AddScreen
+ * nxagentOpenScreen
+ * InitInput
+ */
+
+int nxagentDoFullGeneration = 1;
+
+ /*
+ * 1 if agent running as X2goAgent
+ * 0 if NX Agent
+ */
+int nxagentX2go;
+
+/*
+ * Checking if agent is x2go agent
+ */
+
+void checkX2goAgent()
+{
+ extern const char *__progname;
+ if( strcasecmp(__progname,"x2goagent") == 0)
+ {
+ fprintf(stderr, "\nrunning as X2Go Agent\n");
+ nxagentX2go=1;
+ }
+ else
+ nxagentX2go=0;
+}
+
+
+/*
+ * Called at X server's initialization.
+ */
+
+void InitOutput(ScreenInfo *screenInfo, int argc, char *argv[])
+{
+ char *authority;
+ int i;
+
+ #ifdef __sun
+
+ char *environment;
+
+ #endif
+
+ /*
+ * Check if we running as X2Go Agent
+ */
+ checkX2goAgent();
+
+ /*
+ * Print our pid and version information.
+ */
+
+ if (serverGeneration <= 1)
+ {
+ fprintf(stderr, "\nNXAGENT - Version " NXAGENT_VERSION_STRING "\n\n");
+ fprintf(stderr, "Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com)\n");
+ fprintf(stderr, "Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de>\n");
+ fprintf(stderr, "Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>\n");
+ fprintf(stderr, "Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de>\n");
+ fprintf(stderr, "Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de>\n");
+ fprintf(stderr, "Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com)\n");
+ fprintf(stderr, "See https://github.com/ArcticaProject/nx-libs for more information.\n\n");
+
+ fprintf(stderr, "Info: Agent running with pid '%d'.\n", getpid());
+
+ fprintf(stderr, "Session: Starting session at '%s'.\n", GetTimeAsString());
+ saveAgentState("STARTING");
+ }
+
+ /*
+ * Avoid slowness due to buggy_repeat workaround
+ * in libcairo versions >= 1.10.
+ */
+
+ SetVendorRelease(70000000);
+
+ /*
+ * Init the time count for image rate.
+ */
+
+ if (nxagentOption(ImageRateLimit) != 0)
+ {
+ fprintf(stderr, "Info: Image rate limit set to %u kB/s.\n", nxagentOption(ImageRateLimit));
+ }
+
+ /*
+ * Unset the LD_LIBRARY_PATH variable in
+ * Popen() before calling execl() in the
+ * child process.
+ */
+
+ NXUnsetLibraryPath(1);
+
+ if (serverGeneration == 1)
+ {
+ AddCallback(&ServerGrabCallback, nxagentGrabServerCallback, NULL);
+ }
+
+ if (nxagentUserDefinedFontPath == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "InitOutput: Calling nxagentVerifyDefaultFontPath.\n");
+ #endif
+
+ nxagentVerifyDefaultFontPath();
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "InitOutput: User defined font path. Skipping the check on the fonts dir.\n");
+ }
+ #endif
+
+ if ((authority = getenv("NX_XAUTHORITY")))
+ {
+ #ifdef __sun
+
+ environment = malloc(15 + strlen(authority));
+
+ sprintf(environment, "XAUTHORITY=%s", authority);
+
+ if (putenv(environment) < 0)
+
+ #else
+
+ if (setenv("XAUTHORITY", authority, True) < 0)
+
+ #endif
+
+ {
+ fprintf(stderr, "Warning: Couldn't set the XAUTHORITY environment to [%s]\n",
+ authority);
+ }
+ }
+
+ nxagentInitBSPixmapList();
+
+ /*
+ * Open the display. We are at the early startup and
+ * the information we'll get from the remote X server
+ * will mandate some of the characteristics of the
+ * session, like the screen depth. Note that this re-
+ * liance on the remote display at session startup
+ * should be removed. We should always operate at 32
+ * bpp, internally, and do the required translations
+ * as soon as the graphic operation needs to be real-
+ * ized on the remote display.
+ */
+
+ nxagentOpenDisplay(argc, argv);
+
+/*
+FIXME: These variables, if not removed at all because have probably
+ become useless, should be moved to Display.h and Display.c.
+*/
+ nxagentBackingStore = XDoesBackingStore(DefaultScreenOfDisplay(nxagentDisplay));
+
+ #ifdef TEST
+ fprintf(stderr, "InitOutput: Remote display backing store support [%d].\n",
+ nxagentBackingStore);
+ #endif
+
+ nxagentSaveUnder = XDoesSaveUnders(DefaultScreenOfDisplay(nxagentDisplay));
+
+ #ifdef TEST
+ fprintf(stderr, "InitOutput: Remote display save under support [%d].\n",
+ nxagentSaveUnder);
+ #endif
+
+ /*
+ * Initialize the basic screen info.
+ */
+
+ nxagentSetScreenInfo(screenInfo);
+
+ /*
+ * Initialize pixmap formats for this screen.
+ */
+
+ nxagentSetPixmapFormats(screenInfo);
+
+ /*
+ * Get our own privates' index.
+ */
+
+ nxagentWindowPrivateIndex = AllocateWindowPrivateIndex();
+ nxagentGCPrivateIndex = AllocateGCPrivateIndex();
+ RT_NX_GC = CreateNewResourceType(nxagentDestroyNewGCResourceType);
+#ifdef HAS_XFONT2
+ nxagentFontPrivateIndex = xfont2_allocate_font_private_index();
+#else
+ nxagentFontPrivateIndex = AllocateFontPrivateIndex();
+#endif /* HAS_XFONT2 */
+ RT_NX_FONT = CreateNewResourceType(nxagentDestroyNewFontResourceType);
+ nxagentClientPrivateIndex = AllocateClientPrivateIndex();
+ nxagentPixmapPrivateIndex = AllocatePixmapPrivateIndex();
+ RT_NX_PIXMAP = CreateNewResourceType(nxagentDestroyNewPixmapResourceType);
+
+ RT_NX_CORR_BACKGROUND = CreateNewResourceType(nxagentDestroyCorruptedBackgroundResource);
+ RT_NX_CORR_WINDOW = CreateNewResourceType(nxagentDestroyCorruptedWindowResource);
+ RT_NX_CORR_PIXMAP = CreateNewResourceType(nxagentDestroyCorruptedPixmapResource);
+
+ fbGCPrivateIndex = AllocateGCPrivateIndex();
+
+ if (nxagentNumScreens == 0)
+ {
+ nxagentNumScreens = 1;
+ }
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ AddScreen(nxagentOpenScreen, argc, argv);
+ }
+
+ nxagentNumScreens = screenInfo->numScreens;
+
+ /*
+ * Initialize the GCs used by the synchro-
+ * nization put images. We do it here beca-
+ * use we use the nxagentDefaultScreen.
+ */
+
+ nxagentAllocateGraphicContexts();
+
+ nxagentDoFullGeneration = nxagentFullGeneration;
+
+ /*
+ * Use a solid black root window
+ * background.
+ */
+
+ blackRoot = TRUE;
+
+ nxagentInitKeystrokes(False);
+}
+
+void
+nxagentNotifyConnection(int fd, int ready, void *data)
+{
+ nxagentDispatchEvents(NULL);
+}
+
+void InitInput(argc, argv)
+ int argc;
+ char *argv[];
+{
+ void *ptr, *kbd;
+
+ ptr = AddInputDevice(nxagentPointerProc, True);
+ kbd = AddInputDevice(nxagentKeyboardProc, True);
+
+ RegisterPointerDevice(ptr);
+ RegisterKeyboardDevice(kbd);
+
+ mieqInit(kbd, ptr);
+
+ /*
+ * Add the display descriptor to the
+ * set of descriptors awaited by the
+ * dispatcher.
+ */
+
+ nxagentAddXConnection();
+
+ if (nxagentOption(Shadow))
+ {
+ RegisterBlockAndWakeupHandlers(nxagentShadowBlockHandler, nxagentShadowWakeupHandler, NULL);
+ }
+ else
+ {
+ RegisterBlockAndWakeupHandlers(nxagentBlockHandler, nxagentWakeupHandler, NULL);
+ }
+
+ /*
+ * We let the proxy flush the link on our behalf
+ * after having opened the display. We are now
+ * entering the dispatcher. From now on we'll
+ * flush the proxy link explicitly.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "InitInput: Setting the NX flush policy to deferred.\n");
+ #endif
+
+ NXSetDisplayPolicy(nxagentDisplay, NXPolicyDeferred);
+}
+
+/*
+ * DDX specific abort routine. This is called
+ * by AbortServer() that, in turn, is called
+ * by FatalError().
+ */
+
+void AbortDDX()
+{
+ nxagentDoFullGeneration = True;
+
+ nxagentCloseDisplay();
+
+ /*
+ * Do the required finalization if we
+ * are not going through the normal
+ * X server shutdown.
+ */
+
+ if ((dispatchException & DE_TERMINATE) == 0)
+ {
+ nxagentAbortDisplay();
+ }
+}
+
+/*
+ * Called by GiveUp().
+ */
+
+void ddxGiveUp()
+{
+ AbortDDX();
+}
+
+void ddxBeforeReset(void)
+{
+}
+
+void OsVendorInit()
+{
+ return;
+}
+
+void OsVendorFatalError()
+{
+ /*
+ * Let the session terminate gracely
+ * from an user's standpoint.
+ */
+
+ fprintf(stderr, "Session: Aborting session at '%s'.\n", GetTimeAsString());
+
+ fprintf(stderr, "Session: Session aborted at '%s'.\n", GetTimeAsString());
+}
+
+void OsVendorVErrorFFunction(const char *f, va_list args)
+{
+ if (OsVendorVErrorFFatal == 0)
+ {
+ char buffer[1024];
+
+ vsnprintf(buffer, sizeof(buffer), f, args);
+
+ nxagentStartRedirectToClientsLog();
+
+ fprintf(stderr, "%s", buffer);
+
+ nxagentEndRedirectToClientsLog();
+ }
+ else
+ {
+ LogVWrite(-1, f, args);
+ }
+}
+
+void OsVendorStartRedirectErrorFFunction()
+{
+ nxagentStartRedirectToClientsLog();
+}
+
+void OsVendorEndRedirectErrorFFunction()
+{
+ nxagentEndRedirectToClientsLog();
+}
+
+ServerGrabInfoRec nxagentGrabServerInfo;
+
+static void nxagentGrabServerCallback(CallbackListPtr *callbacks, void *data,
+ void *args)
+{
+ ServerGrabInfoRec *grab = (ServerGrabInfoRec*)args;
+
+ nxagentGrabServerInfo.client = grab->client;
+ nxagentGrabServerInfo.grabstate = grab->grabstate;
+}
+
+#ifdef DPMSExtension
+
+void DPMSSet(int level)
+{
+}
+
+int DPMSGet(int *level)
+{
+ return -1;
+}
+
+Bool DPMSSupported(void)
+{
+ return 1;
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Init.h b/nx-X11/programs/Xserver/hw/nxagent/Init.h
new file mode 100644
index 000000000..34a17067f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Init.h
@@ -0,0 +1,54 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Init_H__
+#define __Init_H__
+
+extern int nxagentDoFullGeneration;
+
+extern int nxagentBackingStore;
+extern int nxagentSaveUnder;
+
+extern int nxagentX2go;
+
+extern ServerGrabInfoRec nxagentGrabServerInfo;
+
+void nxagentNotifyConnection(int fd, int ready, void *data);
+
+#endif /* __Init_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
new file mode 100644
index 000000000..02b60bef4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.c
@@ -0,0 +1,1930 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "X.h"
+#include "Xproto.h"
+#include "keysym.h"
+#include "screenint.h"
+#include "inputstr.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Keyboard.h"
+#include "Events.h"
+#include "Options.h"
+#include "Error.h"
+
+#include "compext/Compext.h"
+
+#include <nx/Shadow.h>
+
+#ifdef XKB
+
+#include "globals.h"
+#include "property.h"
+#include "Init.h"
+
+#include <nx-X11/extensions/XKB.h>
+
+/*
+ we need the client side header here, xkbsrv.h will not work because
+ server and libX11 have different struct sizes on
+ 64bit. Interestingly upstream xnest does not take care of this.
+*/
+#include <nx-X11/extensions/XKBsrv.h>
+#include <nx-X11/extensions/XKBconfig.h>
+
+#include "Xatom.h"
+
+#include <errno.h>
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options);
+
+static void nxagentKeycodeConversionSetup(void);
+
+#endif /* XKB */
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+
+#ifdef WATCH
+#include "unistd.h"
+#endif
+
+/*
+ * Unfortunately we cannot just include XKBlib.h.
+ * It conflicts with the server side definitions
+ * of the same symbols. This is more a X problem
+ * than our.
+ */
+
+#ifdef XKB
+
+extern Bool XkbQueryExtension(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ int * /* opcodeReturn */,
+ int * /* eventBaseReturn */,
+ int * /* errorBaseReturn */,
+ int * /* majorRtrn */,
+ int * /* minorRtrn */
+#endif
+);
+
+extern XkbDescPtr XkbGetKeyboard(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ unsigned int /* which */,
+ unsigned int /* deviceSpec */
+#endif
+);
+
+extern Status XkbGetControls(
+#if NeedFunctionPrototypes
+ Display * /* dpy */,
+ unsigned long /* which */,
+ XkbDescPtr /* desc */
+#endif
+);
+
+#ifndef XKB_BASE_DIRECTORY
+#define XKB_BASE_DIRECTORY "/usr/share/X11/xkb"
+#endif
+#ifndef XKB_ALTERNATE_BASE_DIRECTORY
+#define XKB_ALTERNATE_BASE_DIRECTORY "/usr/X11R6/lib/X11/xkb"
+#endif
+#ifndef XKB_CONFIG_FILE_NX
+#define XKB_CONFIG_FILE_NX "/etc/nxagent/nxagent.keyboard"
+#endif
+#ifndef XKB_CONFIG_FILE_X2GO
+#define XKB_CONFIG_FILE_X2GO "/etc/x2go/x2goagent.keyboard"
+#endif
+#ifndef XKB_DFLT_RULES_FILE
+#define XKB_DFLT_RULES_FILE "xfree86"
+#endif
+#ifndef XKB_ALTS_RULES_FILE
+#define XKB_ALTS_RULES_FILE "xorg"
+#endif
+#ifndef XKB_DFLT_KB_LAYOUT
+#define XKB_DFLT_KB_LAYOUT "us"
+#endif
+#ifndef XKB_DFLT_KB_MODEL
+#define XKB_DFLT_KB_MODEL "pc102"
+#endif
+#ifndef XKB_DFLT_KB_VARIANT
+#define XKB_DFLT_KB_VARIANT NULL
+#endif
+#ifndef XKB_DFLT_KB_OPTIONS
+#define XKB_DFLT_KB_OPTIONS NULL
+#endif
+
+extern int XkbDfltRepeatDelay;
+extern int XkbDfltRepeatInterval;
+
+#endif /* XKB */
+
+/*
+ * Save the values queried from X server.
+ */
+
+XkbAgentInfoRec nxagentXkbInfo = { -1, -1, -1, -1, -1 };
+
+/*
+ * Keyboard status, updated through XKB
+ * events.
+ */
+
+XkbAgentStateRec nxagentXkbState = { 0, 0, 0, 0, 0 };
+
+/*
+ * Info for disabling/enabling Xkb extension.
+ */
+
+XkbWrapperRec nxagentXkbWrapper;
+
+extern char *nxagentKeyboard;
+
+static char *nxagentXkbGetRules(void);
+
+unsigned int nxagentAltMetaMask;
+unsigned int nxagentAltMask;
+unsigned int nxagentMetaMask;
+unsigned int nxagentCapsMask;
+unsigned int nxagentNumlockMask;
+
+static void nxagentCheckModifierMasks(CARD8, int);
+
+CARD8 nxagentCapsLockKeycode = 66;
+CARD8 nxagentNumLockKeycode = 77;
+
+static void nxagentCheckRemoteKeycodes(void);
+
+static CARD8 nxagentConvertedKeycodes[] =
+{
+ /* evdev pc105*/
+ /* 0 */ 0,
+ /* 1 */ 1,
+ /* 2 */ 2,
+ /* 3 */ 3,
+ /* 4 */ 4,
+ /* 5 */ 5,
+ /* 6 */ 6,
+ /* 7 */ 7,
+ /* 8 */ 8,
+ /* 9 */ 9,
+ /* 10 */ 10,
+ /* 11 */ 11,
+ /* 12 */ 12,
+ /* 13 */ 13,
+ /* 14 */ 14,
+ /* 15 */ 15,
+ /* 16 */ 16,
+ /* 17 */ 17,
+ /* 18 */ 18,
+ /* 19 */ 19,
+ /* 20 */ 20,
+ /* 21 */ 21,
+ /* 22 */ 22,
+ /* 23 */ 23,
+ /* 24 */ 24,
+ /* 25 */ 25,
+ /* 26 */ 26,
+ /* 27 */ 27,
+ /* 28 */ 28,
+ /* 29 */ 29,
+ /* 30 */ 30,
+ /* 31 */ 31,
+ /* 32 */ 32,
+ /* 33 */ 33,
+ /* 34 */ 34,
+ /* 35 */ 35,
+ /* 36 */ 36,
+ /* 37 */ 37,
+ /* 38 */ 38,
+ /* 39 */ 39,
+ /* 40 */ 40,
+ /* 41 */ 41,
+ /* 42 */ 42,
+ /* 43 */ 43,
+ /* 44 */ 44,
+ /* 45 */ 45,
+ /* 46 */ 46,
+ /* 47 */ 47,
+ /* 48 */ 48,
+ /* 49 */ 49,
+ /* 50 */ 50,
+ /* 51 */ 51,
+ /* 52 */ 52,
+ /* 53 */ 53,
+ /* 54 */ 54,
+ /* 55 */ 55,
+ /* 56 */ 56,
+ /* 57 */ 57,
+ /* 58 */ 58,
+ /* 59 */ 59,
+ /* 60 */ 60,
+ /* 61 */ 61,
+ /* 62 */ 62,
+ /* 63 */ 63,
+ /* 64 */ 64,
+ /* 65 */ 65,
+ /* 66 */ 66,
+ /* 67 */ 67,
+ /* 68 */ 68,
+ /* 69 */ 69,
+ /* 70 */ 70,
+ /* 71 */ 71,
+ /* 72 */ 72,
+ /* 73 */ 73,
+ /* 74 */ 74,
+ /* 75 */ 75,
+ /* 76 */ 76,
+ /* 77 */ 77,
+ /* 78 */ 78,
+ /* 79 */ 79,
+ /* 80 */ 80,
+ /* 81 */ 81,
+ /* 82 */ 82,
+ /* 83 */ 83,
+ /* 84 */ 84,
+ /* 85 */ 85,
+ /* 86 */ 86,
+ /* 87 */ 87,
+ /* 88 */ 88,
+ /* 89 */ 89,
+ /* 90 */ 90,
+ /* 91 */ 91,
+ /* 92 */ 124,
+ /* 93 */ 93,
+ /* 94 */ 94,
+ /* 95 */ 95,
+ /* 96 */ 96,
+ /* 97 */ 211,
+ /* 98 */ 98,
+ /* 99 */ 99,
+ /* 100 */ 100,
+ /* 101 */ 208,
+ /* 102 */ 102,
+ /* 103 */ 103,
+ /* 104 */ 108,
+ /* 105 */ 109,
+ /* 106 */ 112,
+ /* 107 */ 111,
+ /* 108 */ 113,
+ /* 109 */ 109,
+ /* 110 */ 97,
+ /* 111 */ 98,
+ /* 112 */ 99,
+ /* 113 */ 100,
+ /* 114 */ 102,
+ /* 115 */ 103,
+ /* 116 */ 104,
+ /* 117 */ 105,
+ /* 118 */ 106,
+ /* 119 */ 107,
+ /* 120 */ 120,
+ /* 121 */ 121,
+ /* 122 */ 122,
+ /* 123 */ 123,
+ /* 124 */ 124,
+ /* 125 */ 126,
+ /* 126 */ 126,
+ /* 127 */ 110,
+ /* 128 */ 128,
+ /* 129 */ 129,
+ /* 130 */ 130,
+ /* 131 */ 131,
+ /* 132 */ 133,
+ /* 133 */ 115,
+ /* 134 */ 116,
+ /* 135 */ 117,
+ /* 136 */ 136,
+ /* 137 */ 137,
+ /* 138 */ 138,
+ /* 139 */ 139,
+ /* 140 */ 140,
+ /* 141 */ 141,
+ /* 142 */ 142,
+ /* 143 */ 143,
+ /* 144 */ 144,
+ /* 145 */ 145,
+ /* 146 */ 146,
+ /* 147 */ 147,
+ /* 148 */ 148,
+ /* 149 */ 149,
+ /* 150 */ 150,
+ /* 151 */ 151,
+ /* 152 */ 152,
+ /* 153 */ 153,
+ /* 154 */ 154,
+ /* 155 */ 155,
+ /* 156 */ 156,
+ /* 157 */ 157,
+ /* 158 */ 158,
+ /* 159 */ 159,
+ /* 160 */ 160,
+ /* 161 */ 161,
+ /* 162 */ 162,
+ /* 163 */ 163,
+ /* 164 */ 164,
+ /* 165 */ 165,
+ /* 166 */ 166,
+ /* 167 */ 167,
+ /* 168 */ 168,
+ /* 169 */ 169,
+ /* 170 */ 170,
+ /* 171 */ 171,
+ /* 172 */ 172,
+ /* 173 */ 173,
+ /* 174 */ 174,
+ /* 175 */ 175,
+ /* 176 */ 176,
+ /* 177 */ 177,
+ /* 178 */ 178,
+ /* 179 */ 179,
+ /* 180 */ 180,
+ /* 181 */ 181,
+ /* 182 */ 182,
+ /* 183 */ 183,
+ /* 184 */ 184,
+ /* 185 */ 185,
+ /* 186 */ 186,
+ /* 187 */ 187,
+ /* 188 */ 188,
+ /* 189 */ 189,
+ /* 190 */ 190,
+ /* 191 */ 118,
+ /* 192 */ 119,
+ /* 193 */ 120,
+ /* 194 */ 121,
+ /* 195 */ 122,
+ /* 196 */ 196,
+ /* 197 */ 197,
+ /* 198 */ 198,
+ /* 199 */ 199,
+ /* 200 */ 200,
+ /* 201 */ 201,
+ /* 202 */ 202,
+ /* 203 */ 93,
+ /* 204 */ 125,
+ /* 205 */ 156,
+ /* 206 */ 127,
+ /* 207 */ 128,
+ /* 208 */ 208,
+ /* 209 */ 209,
+ /* 210 */ 210,
+ /* 211 */ 211,
+ /* 212 */ 212,
+ /* 213 */ 213,
+ /* 214 */ 214,
+ /* 215 */ 215,
+ /* 216 */ 216,
+ /* 217 */ 217,
+ /* 218 */ 218,
+ /* 219 */ 219,
+ /* 220 */ 220,
+ /* 221 */ 221,
+ /* 222 */ 222,
+ /* 223 */ 223,
+ /* 224 */ 224,
+ /* 225 */ 225,
+ /* 226 */ 226,
+ /* 227 */ 227,
+ /* 228 */ 228,
+ /* 229 */ 229,
+ /* 230 */ 230,
+ /* 231 */ 231,
+ /* 232 */ 232,
+ /* 233 */ 233,
+ /* 234 */ 234,
+ /* 235 */ 235,
+ /* 236 */ 236,
+ /* 237 */ 237,
+ /* 238 */ 238,
+ /* 239 */ 239,
+ /* 240 */ 240,
+ /* 241 */ 241,
+ /* 242 */ 242,
+ /* 243 */ 243,
+ /* 244 */ 244,
+ /* 245 */ 245,
+ /* 246 */ 246,
+ /* 247 */ 247,
+ /* 248 */ 248,
+ /* 249 */ 249,
+ /* 250 */ 250,
+ /* 251 */ 251,
+ /* 252 */ 252,
+ /* 253 */ 253,
+ /* 254 */ 254,
+ /* 255 */ 255
+};
+
+static int nxagentKeycodeConversion = 0;
+
+CARD8 nxagentConvertKeycode(CARD8 k)
+{
+ if (nxagentKeycodeConversion != 0)
+ {
+ #ifdef DEBUG
+ if (k != nxagentConvertedKeycodes[k])
+ fprintf(stderr, "nxagentConvertKeycode: converting keycode [%d] to [%d]\n", k, nxagentConvertedKeycodes[k]);
+ #endif
+
+ return nxagentConvertedKeycodes[k];
+ }
+ else
+ {
+ return k;
+ }
+}
+
+static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup);
+
+static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev);
+
+static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev);
+
+static void nxagentCheckXkbBaseDirectory(void)
+{
+
+ /*
+ * Set XkbBaseDirectory global
+ * variable appropriately.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "Before calling _NXGetXkbBasePath:\n");
+
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "XkbBaseDirectory variable [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ XkbBaseDirectory = _NXGetXkbBasePath(XkbBaseDirectory);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "After calling _NXGetXkbBasePath:\n");
+
+ fprintf(stderr, "nxagentCheckXkbBaseDirectory: "
+ "XkbBaseDirectory variable [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ return;
+}
+
+static char *nxagentXkbGetRules()
+{
+ int ret;
+ int size, sizeDflt, sizeAlt;
+ char *path;
+ struct stat buf;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentXkbGetRules: XkbBaseDirectory [%s].\n",
+ XkbBaseDirectory);
+ #endif
+
+ sizeDflt = strlen(XKB_DFLT_RULES_FILE);
+ sizeAlt = strlen(XKB_ALTS_RULES_FILE);
+ size = strlen(XkbBaseDirectory) + strlen("/rules/");
+ size += (sizeDflt > sizeAlt) ? sizeDflt : sizeAlt;
+
+ if ((path = malloc((size + 1) * sizeof(char))) == NULL)
+ {
+ FatalError("nxagentXkbGetRules: malloc failed.");
+ }
+
+ strcpy(path, XkbBaseDirectory);
+ strcat(path, "/rules/");
+ strcat(path, XKB_DFLT_RULES_FILE);
+ ret = stat(path, &buf);
+
+ if (ret == 0)
+ {
+ free(path);
+ return XKB_DFLT_RULES_FILE;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret));
+ #endif
+
+ strcpy(path, XkbBaseDirectory);
+ strcat(path, "/rules/");
+ strcat(path, XKB_ALTS_RULES_FILE);
+ ret = stat(path, &buf);
+
+ if (ret == 0)
+ {
+ free(path);
+ return XKB_ALTS_RULES_FILE;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentXkbGetRules: WARNING! Failed to stat file [%s]: %s.\n", path, strerror(ret));
+ #endif
+
+ free(path);
+ return XKB_DFLT_RULES_FILE;
+}
+
+void nxagentBell(int volume, DeviceIntPtr pDev, void * ctrl, int cls)
+{
+ XBell(nxagentDisplay, volume);
+}
+
+void nxagentChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
+{
+ #ifdef XKB
+
+ XkbSrvInfoPtr xkbi;
+ XkbControlsPtr xkbc;
+
+ if (!noXkbExtension)
+ {
+ xkbi = pDev -> key -> xkbInfo;
+ xkbc = xkbi -> desc -> ctrls;
+
+ /*
+ * We want to prevent agent generating auto-repeated
+ * keystrokes. Let's intercept any attempt by appli-
+ * cations to change the default timeouts on the
+ * nxagent device.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay was [%d] interval was [%d].\n",
+ xkbc -> repeat_delay, xkbc -> repeat_interval);
+ #endif
+
+ xkbc -> repeat_delay = ~ 0;
+ xkbc -> repeat_interval = ~ 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: Repeat delay is now [%d] interval is now [%d].\n",
+ xkbc -> repeat_delay, xkbc -> repeat_interval);
+ #endif
+ }
+
+ #endif
+
+ /*
+ * If enabled, propagate the changes to the
+ * devices attached to the real X server.
+ */
+
+ if (nxagentOption(DeviceControl) == True)
+ {
+ unsigned long value_mask;
+ XKeyboardControl values;
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Propagating changes to keyboard settings.\n");
+ #endif
+
+ value_mask = KBKeyClickPercent |
+ KBBellPercent |
+ KBBellPitch |
+ KBBellDuration;
+
+ values.key_click_percent = ctrl->click;
+ values.bell_percent = ctrl->bell;
+ values.bell_pitch = ctrl->bell_pitch;
+ values.bell_duration = ctrl->bell_duration;
+
+ /*
+ * Don't propagate the auto repeat mode. It is forced to be
+ * off in the agent server.
+ *
+ * value_mask |= KBAutoRepeatMode;
+ * values.auto_repeat_mode = ctrl->autoRepeat ?
+ * AutoRepeatModeOn : AutoRepeatModeOff;
+ */
+
+ XChangeKeyboardControl(nxagentDisplay, value_mask, &values);
+
+ /*
+ * At this point, we need to walk through the vector and
+ * compare it to the current server vector. If there are
+ * differences, report them.
+ */
+
+ value_mask = KBLed | KBLedMode;
+
+ for (i = 1; i <= 32; i++)
+ {
+ values.led = i;
+ values.led_mode = (ctrl->leds & (1 << (i - 1))) ? LedModeOn : LedModeOff;
+
+ XChangeKeyboardControl(nxagentDisplay, value_mask, &values);
+ }
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeKeyboardControl: WARNING! Not propagating changes to keyboard settings.\n");
+ #endif
+}
+
+int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff)
+{
+ XModifierKeymap *modifier_keymap;
+ KeySym *keymap;
+ int mapWidth;
+ int min_keycode, max_keycode;
+ KeySymsRec keySyms;
+ CARD8 modmap[256];
+ int i, j;
+ XKeyboardState values;
+ char *model = NULL, *layout = NULL;
+ int free_model = 0, free_layout = 0;
+ XkbDescPtr xkb = NULL;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_INIT].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 9.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ /*
+ * Prevent agent from generating auto-repeat keystroke.
+ * Note that this is working only if XKB is enabled.
+ * A better solution should account cases where XKB is
+ * not available. Check also the behaviour of the
+ * DeviceControl nxagent option.
+ */
+
+ XkbDfltRepeatDelay = ~ 0;
+ XkbDfltRepeatInterval = ~ 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Set repeat delay to [%u] interval to [%u].\n",
+ XkbDfltRepeatDelay, XkbDfltRepeatInterval);
+ #endif
+
+ modifier_keymap = XGetModifierMapping(nxagentDisplay);
+
+ if (modifier_keymap == NULL)
+ {
+ return -1;
+ }
+
+ XDisplayKeycodes(nxagentDisplay, &min_keycode, &max_keycode);
+#ifdef _XSERVER64
+ {
+ KeySym64 *keymap64;
+ int i, len;
+ keymap64 = XGetKeyboardMapping(nxagentDisplay,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &mapWidth);
+
+ if (keymap64 == NULL)
+ {
+ XFreeModifiermap(modifier_keymap);
+
+ return -1;
+ }
+
+ len = (max_keycode - min_keycode + 1) * mapWidth;
+ keymap = (KeySym *)malloc(len * sizeof(KeySym));
+ for(i = 0; i < len; ++i)
+ keymap[i] = keymap64[i];
+ XFree(keymap64);
+ }
+
+#else /* #ifdef _XSERVER64 */
+
+ keymap = XGetKeyboardMapping(nxagentDisplay,
+ min_keycode,
+ max_keycode - min_keycode + 1,
+ &mapWidth);
+
+ if (keymap == NULL)
+ {
+ XFreeModifiermap(modifier_keymap);
+
+ return -1;
+ }
+
+#endif /* #ifdef _XSERVER64 */
+
+ nxagentAltMetaMask = 0;
+ nxagentAltMask = 0;
+ nxagentMetaMask = 0;
+ nxagentCapsMask = 0;
+ nxagentNumlockMask = 0;
+
+ for (i = 0; i < 256; i++)
+ modmap[i] = 0;
+ for (j = 0; j < 8; j++)
+ for(i = 0; i < modifier_keymap->max_keypermod; i++) {
+ CARD8 keycode;
+ if ((keycode =
+ modifier_keymap->
+ modifiermap[j * modifier_keymap->max_keypermod + i]))
+ modmap[keycode] |= 1<<j;
+
+ if (keycode > 0)
+ {
+ nxagentCheckModifierMasks(keycode, j);
+ }
+ }
+ XFreeModifiermap(modifier_keymap);
+
+ nxagentCheckRemoteKeycodes();
+
+ keySyms.minKeyCode = min_keycode;
+ keySyms.maxKeyCode = max_keycode;
+ keySyms.mapWidth = mapWidth;
+ keySyms.map = keymap;
+
+#ifdef XKB
+
+ /*
+ * First of all the validity
+ * of XkbBaseDirectory global
+ * variable is checked.
+ */
+
+ nxagentCheckXkbBaseDirectory();
+
+ if (noXkbExtension) {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No XKB extension.\n");
+ #endif
+
+XkbError:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: XKB error.\n");
+ #endif
+
+ XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+ xkb = NULL;
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+#endif
+ XGetKeyboardControl(nxagentDisplay, &values);
+
+ memmove((char *) defaultKeyboardControl.autoRepeats,
+ (char *) values.auto_repeats, sizeof(values.auto_repeats));
+
+ #ifdef TEST
+ {
+ int ret =
+ #endif
+ InitKeyboardDeviceStruct((DevicePtr) pDev, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: InitKeyboardDeviceStruct returns [%d].\n", ret);
+ }
+ #endif
+
+#ifdef XKB
+ } else {
+ FILE *file;
+ XkbConfigRtrnRec config;
+
+ char *nxagentXkbConfigFilePath;
+
+ XkbComponentNamesRec names;
+ char *rules, *variants, *options;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using XKB extension.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: nxagentKeyboard is [%s].\n", nxagentKeyboard ? nxagentKeyboard : "NULL");
+ #endif
+
+ memset(&names, 0, sizeof(XkbComponentNamesRec));
+
+ rules = nxagentXkbGetRules();
+
+ if ((nxagentKeyboard != NULL) && (strcmp(nxagentKeyboard, "query") != 0))
+ {
+ for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++);
+
+ if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0)
+ {
+ ErrorF("Warning: Wrong keyboard type: %s.\n", nxagentKeyboard);
+
+ goto XkbError;
+ }
+
+ free_model = 1;
+ model = strndup(nxagentKeyboard, i);
+
+ free_layout = 1;
+ layout = strdup(&nxagentKeyboard[i + 1]);
+
+ /*
+ * There is no description for pc105 on Solaris.
+ * Need to revert to the closest approximation.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using keyboard model [%s] with layout [%s].\n",
+ model, layout);
+ #endif
+
+ #ifdef __sun
+
+ if (strcmp(model, "pc105") == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: WARNING! Keyboard model 'pc105' unsupported on Solaris.\n");
+
+ fprintf(stderr, "nxagentKeyboardProc: WARNING! Forcing keyboard model to 'pc104'.\n");
+ #endif
+
+ strcpy(model, "pc104");
+ }
+
+ #endif
+ }
+ else
+ {
+ layout = XKB_DFLT_KB_LAYOUT;
+ model = XKB_DFLT_KB_MODEL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Using default keyboard: model [%s] layout [%s].\n",
+ model, layout);
+ #endif
+ }
+
+ variants = XKB_DFLT_KB_VARIANT;
+ options = XKB_DFLT_KB_OPTIONS;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: XkbInitialMap [%s]\n", XkbInitialMap ? XkbInitialMap : "NULL");
+ #endif
+
+ if (XkbInitialMap) {
+ if ((names.keymap = strchr(XkbInitialMap, '/')) != NULL)
+ ++names.keymap;
+ else
+ names.keymap = XkbInitialMap;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Init XKB extension.\n");
+ #endif
+
+ if (XkbQueryExtension(nxagentDisplay,
+ &nxagentXkbInfo.Opcode,
+ &nxagentXkbInfo.EventBase,
+ &nxagentXkbInfo.ErrorBase,
+ &nxagentXkbInfo.MajorVersion,
+ &nxagentXkbInfo.MinorVersion) == 0)
+ {
+ ErrorF("Unable to initialize XKEYBOARD extension.\n");
+
+ goto XkbError;
+ }
+
+ xkb = XkbGetKeyboard(nxagentDisplay, XkbGBN_AllComponentsMask, XkbUseCoreKbd);
+
+ nxagentKeycodeConversionSetup();
+
+ if (xkb == NULL || xkb->geom == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No current keyboard.\n");
+ if (xkb == NULL)
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb is null.\n");
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeyboardProc: xkb->geom is null.\n");
+ }
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device.\n");
+ #endif
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device: "
+ "[rules='%s',model='%s',layout='%s',variants='%s',options='%s'].\n",
+ rules, model, layout, variants, options);
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((void *)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ if (!nxagentKeyboard || strcmp(nxagentKeyboard, "query") == 0)
+ {
+ goto XkbError;
+ }
+
+ goto XkbEnd;
+ }
+
+ XkbGetControls(nxagentDisplay, XkbAllControlsMask, xkb);
+
+ if (nxagentX2go)
+ nxagentXkbConfigFilePath = strdup(XKB_CONFIG_FILE_X2GO);
+ else
+ nxagentXkbConfigFilePath = strdup(XKB_CONFIG_FILE_NX);
+
+ if (nxagentXkbConfigFilePath == NULL)
+ {
+ FatalError("nxagentKeyboardProc: malloc failed.");
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: nxagentXkbConfigFilePath [%s].\n",
+ nxagentXkbConfigFilePath);
+ #endif
+
+ if ((file = fopen(nxagentXkbConfigFilePath, "r")) != NULL) {
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Going to parse config file.\n");
+ #endif
+
+ if (XkbCFParse(file, XkbCFDflts, xkb, &config) == 0) {
+ ErrorF("Error parsing config file.\n");
+
+ free(nxagentXkbConfigFilePath);
+
+ fclose(file);
+ goto XkbError;
+ }
+ if (config.rules_file)
+ rules = config.rules_file;
+ if (config.model)
+ {
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+ model = config.model;
+ }
+ if (config.layout)
+ {
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+ layout = config.layout;
+ }
+ if (config.variant)
+ variants = config.variant;
+ if (config.options)
+ options = config.options;
+
+ free(nxagentXkbConfigFilePath);
+
+ fclose(file);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: No config file, going to set rules and init device.\n");
+ #endif
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device: "
+ "[rules='%s',model='%s',layout='%s',variants='%s',options='%s'].\n",
+ rules, model, layout, variants, options);
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((void *)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+
+ free(nxagentXkbConfigFilePath);
+
+ if (!nxagentKeyboard || strcmp(nxagentKeyboard, "query") == 0)
+ {
+ goto XkbError;
+ }
+
+ goto XkbEnd;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device.\n");
+ #endif
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentKeyboardProc: Going to set rules and init device: "
+ "[rules='%s',model='%s',layout='%s',variants='%s',options='%s'].\n",
+ rules, model, layout, variants, options);
+ #endif
+
+ XkbSetRulesDflts(rules, model, layout, variants, options);
+ XkbInitKeyboardDeviceStruct((void *)pDev, &names, &keySyms, modmap,
+ nxagentBell, nxagentChangeKeyboardControl);
+ XkbDDXChangeControls((void *)pDev, xkb->ctrls, xkb->ctrls);
+
+XkbEnd:
+
+ if (nxagentOption(Shadow) == 1 && pDev && pDev->key)
+ {
+ NXShadowInitKeymap(&(pDev->key->curKeySyms));
+ }
+
+ if (free_model)
+ {
+ free_model = 0;
+ free(model);
+ }
+
+ if (free_layout)
+ {
+ free_layout = 0;
+ free(layout);
+ }
+
+ XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+ xkb = NULL;
+ }
+#endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 10.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#1 U 3 2 80320 bits (10 KB) -> 28621 bits (3 KB) -> 26773/1 -> 9540/1 = 2.806:1
+#98 1 256 bits (0 KB) -> 27 bits (0 KB) -> 256/1 -> 27/1 = 9.481:1
+#101 1 32000 bits (4 KB) -> 2940 bits (0 KB) -> 32000/1 -> 2940/1 = 10.884:1
+#119 1 384 bits (0 KB) -> 126 bits (0 KB) -> 384/1 -> 126/1 = 3.048:1
+*/
+
+ sleep(30);
+
+ #endif
+
+#ifdef _XSERVER64
+ free(keymap);
+#else
+ XFree(keymap);
+#endif
+ break;
+ case DEVICE_ON:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_ON].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentKeyboardProc: Watchpoint 11.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#117 1 320 bits (0 KB) -> 52 bits (0 KB) -> 320/1 -> 52/1 = 6.154:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ nxagentEnableKeyboardEvents();
+
+ break;
+
+ case DEVICE_OFF:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_OFF].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ nxagentDisableKeyboardEvents();
+
+ break;
+
+ case DEVICE_CLOSE:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentKeyboardProc: Called for [DEVICE_CLOSE].\n");
+ #endif
+
+ break;
+ }
+
+ return Success;
+}
+
+Bool LegalModifier(key, pDev)
+ unsigned int key;
+ DevicePtr pDev;
+{
+ return TRUE;
+}
+
+void nxagentNotifyKeyboardChanges(int oldMinKeycode, int oldMaxKeycode)
+{
+ #ifdef XKB
+
+ if (!noXkbExtension)
+ {
+ DeviceIntPtr dev;
+ xkbNewKeyboardNotify nkn;
+
+ dev = inputInfo.keyboard;
+
+ memset(&nkn, 0, sizeof(xkbNewKeyboardNotify));
+ nkn.deviceID = nkn.oldDeviceID = dev -> id;
+ nkn.minKeyCode = 8;
+ nkn.maxKeyCode = 255;
+ nkn.oldMinKeyCode = oldMinKeycode;
+ nkn.oldMaxKeyCode = oldMaxKeycode;
+ nkn.requestMajor = XkbReqCode;
+ nkn.requestMinor = X_kbGetKbdByName;
+ nkn.changed = XkbNKN_KeycodesMask;
+
+ XkbSendNewKeyboardNotify(dev, &nkn);
+ }
+ else
+ {
+
+ #endif
+
+ int i;
+ xEvent event;
+
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = MappingNotify;
+ event.u.mappingNotify.request = MappingKeyboard;
+ event.u.mappingNotify.firstKeyCode = inputInfo.keyboard -> key -> curKeySyms.minKeyCode;
+ event.u.mappingNotify.count = inputInfo.keyboard -> key -> curKeySyms.maxKeyCode -
+ inputInfo.keyboard -> key -> curKeySyms.minKeyCode;
+
+ /*
+ * 0 is the server client
+ */
+
+ for (i = 1; i < currentMaxClients; i++)
+ {
+ if (clients[i] && clients[i] -> clientState == ClientStateRunning)
+ {
+ event.u.u.sequenceNumber = clients[i] -> sequence;
+ WriteEventsToClient(clients[i], 1, &event);
+ }
+ }
+
+ #ifdef XKB
+
+ }
+
+ #endif
+
+}
+
+int nxagentResetKeyboard(void)
+{
+ DeviceIntPtr dev = inputInfo.keyboard;
+ DeviceIntPtr devBackup;
+
+ int result;
+ int oldMinKeycode = 8;
+ int oldMaxKeycode = 255;
+
+ int savedBellPercent;
+ int savedBellPitch;
+ int savedBellDuration;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return 0;
+ }
+
+ /*
+ * Save bell settings.
+ */
+
+ savedBellPercent = inputInfo.keyboard -> kbdfeed -> ctrl.bell;
+ savedBellPitch = inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch;
+ savedBellDuration = inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetKeyboard: bellPercent [%d] bellPitch [%d] bellDuration [%d].\n",
+ savedBellPercent, savedBellPitch, savedBellDuration);
+ #endif
+
+ devBackup = malloc(sizeof(DeviceIntRec));
+
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Can't allocate backup structure.\n");
+ #endif
+ }
+ else
+ {
+ memset(devBackup, 0, sizeof(DeviceIntRec));
+ }
+
+ nxagentSaveKeyboardDeviceData(dev, devBackup);
+
+ if (dev->key)
+ {
+ #ifdef XKB
+ if (noXkbExtension == 0 && dev->key->xkbInfo)
+ {
+ oldMinKeycode = dev->key->xkbInfo -> desc -> min_key_code;
+ oldMaxKeycode = dev->key->xkbInfo -> desc -> max_key_code;
+ }
+ #endif
+
+ dev->key=NULL;
+ }
+
+ dev->focus=NULL;
+
+ dev->kbdfeed=NULL;
+
+ #ifdef XKB
+ nxagentTuneXkbWrapper();
+ #endif
+
+ result = (*inputInfo.keyboard -> deviceProc)(inputInfo.keyboard, DEVICE_INIT);
+
+ if (result == Success && inputInfo.keyboard -> key != NULL)
+ {
+
+ /*
+ * Restore bell settings.
+ */
+
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell = savedBellPercent;
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell_pitch = savedBellPitch;
+ inputInfo.keyboard -> kbdfeed -> ctrl.bell_duration = savedBellDuration;
+
+ nxagentNotifyKeyboardChanges(oldMinKeycode, oldMaxKeycode);
+
+ nxagentFreeKeyboardDeviceData(devBackup);
+
+ free(devBackup);
+
+ return 1;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentResetKeyboard: Can't initialize the keyboard device.\n");
+ #endif
+
+ nxagentRestoreKeyboardDeviceData(devBackup, dev);
+
+ return 0;
+ }
+}
+
+void nxagentCheckModifierMasks(CARD8 keycode, int j)
+{
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_L))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ nxagentMetaMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Meta_R))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ nxagentMetaMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_L))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ nxagentAltMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Alt_R))
+ {
+ nxagentAltMetaMask |= 1 << j;
+ nxagentAltMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Num_Lock))
+ {
+ nxagentNumlockMask |= 1 << j;
+ }
+
+ if (keycode == XKeysymToKeycode(nxagentDisplay, XK_Caps_Lock) ||
+ keycode == XKeysymToKeycode(nxagentDisplay, XK_Shift_Lock) )
+ {
+ nxagentCapsMask |= 1 << j;
+ }
+
+}
+
+void nxagentCheckRemoteKeycodes()
+{
+ nxagentCapsLockKeycode = XKeysymToKeycode(nxagentDisplay, XK_Caps_Lock);
+
+ nxagentNumLockKeycode = XKeysymToKeycode(nxagentDisplay, XK_Num_Lock);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCheckRemoteKeycodes: Remote keycodes: CapsLock "
+ "[%d] NumLock [%d].\n", nxagentCapsLockKeycode,
+ nxagentNumLockKeycode);
+ #endif
+}
+
+static int nxagentSaveKeyboardDeviceData(DeviceIntPtr dev, DeviceIntPtr devBackup)
+{
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ devBackup -> key = dev -> key;
+
+ devBackup -> focus = dev -> focus;
+
+ devBackup -> kbdfeed = dev -> kbdfeed;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentSaveKeyboardDeviceData: Saved device data.\n");
+ #endif
+
+ return 1;
+}
+
+static int nxagentRestoreKeyboardDeviceData(DeviceIntPtr devBackup, DeviceIntPtr dev)
+{
+ if (devBackup == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentRestoreKeyboardDeviceData: PANIC! Pointer to backup structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ dev -> key = devBackup -> key;
+
+ dev -> focus = devBackup -> focus;
+
+ dev -> kbdfeed = devBackup -> kbdfeed;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRestoreKeyboardDeviceData: Restored device data.\n");
+ #endif
+
+ return 1;
+}
+
+
+static int nxagentFreeKeyboardDeviceData(DeviceIntPtr dev)
+{
+ KbdFeedbackPtr k, knext;
+
+ if (dev == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentFreeKeyboardDeviceData: PANIC! Pointer to device structure is null.\n");
+ #endif
+
+ return -1;
+ }
+
+ if (dev->key)
+ {
+ #ifdef XKB
+ if (noXkbExtension == 0 && dev->key->xkbInfo)
+ {
+ XkbFreeInfo(dev->key->xkbInfo);
+ dev->key->xkbInfo = NULL;
+ }
+ #endif
+
+ free(dev->key->curKeySyms.map);
+ free(dev->key->modifierKeyMap);
+ free(dev->key);
+
+ dev->key=NULL;
+ }
+
+ if (dev->focus)
+ {
+ free(dev->focus->trace);
+ free(dev->focus);
+ dev->focus=NULL;
+ }
+
+ for (k = dev->kbdfeed; k; k = knext)
+ {
+ knext = k->next;
+ #ifdef XKB
+ if (k->xkb_sli)
+ XkbFreeSrvLedInfo(k->xkb_sli);
+ #endif
+ free(k);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentFreeKeyboardDeviceData: Freed device data.\n");
+ #endif
+
+ return 1;
+}
+
+#if XKB
+
+int ProcXkbInhibited(register ClientPtr client)
+{
+ unsigned char majorop;
+ unsigned char minorop;
+
+ #ifdef TEST
+ fprintf(stderr, "ProcXkbInhibited: Called.\n");
+ #endif
+
+ majorop = ((xReq *)client->requestBuffer)->reqType;
+
+ #ifdef PANIC
+ if (majorop != (unsigned char)nxagentXkbWrapper.base)
+ {
+ fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] but should be [%d].\n",
+ majorop, nxagentXkbWrapper.base);
+ }
+ #endif
+
+ minorop = *((unsigned char *) client->requestBuffer + 1);
+
+ #ifdef TEST
+ fprintf(stderr, "ProcXkbInhibited: MAJOROP is [%d] MINOROP is [%d].\n",
+ majorop, minorop);
+ #endif
+
+ switch (minorop)
+ {
+ case X_kbLatchLockState:
+ case X_kbSetControls:
+ case X_kbSetCompatMap:
+ case X_kbSetIndicatorMap:
+ case X_kbSetNamedIndicator:
+ case X_kbSetNames:
+ case X_kbSetGeometry:
+ case X_kbSetDebuggingFlags:
+ case X_kbSetMap:
+ {
+ return client->noClientException;
+ }
+ case X_kbGetKbdByName:
+ {
+ return BadAccess;
+ }
+ default:
+ {
+ return (client->swapped ? nxagentXkbWrapper.SProcXkbDispatchBackup(client) :
+ nxagentXkbWrapper.ProcXkbDispatchBackup(client));
+ }
+ }
+}
+
+void nxagentInitXkbWrapper(void)
+{
+ ExtensionEntry * extension;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: Called.\n");
+ #endif
+
+ if (nxagentOption(InhibitXkb) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: Nothing to do.\n");
+ #endif
+
+ return;
+ }
+
+ memset(&nxagentXkbWrapper, 0, sizeof(XkbWrapperRec));
+
+ extension = CheckExtension("XKEYBOARD");
+
+ if (extension != NULL)
+ {
+ nxagentXkbWrapper.base = extension -> base;
+ nxagentXkbWrapper.eventBase = extension -> eventBase;
+ nxagentXkbWrapper.errorBase = extension -> errorBase;
+ nxagentXkbWrapper.ProcXkbDispatchBackup = NULL;
+ nxagentXkbWrapper.SProcXkbDispatchBackup = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: base [%d] eventBase [%d] errorBase [%d].\n",
+ extension -> base, extension -> eventBase, extension -> errorBase);
+ #endif
+ }
+ else
+ {
+ nxagentXkbWrapper.base = -1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitXkbWrapper: XKEYBOARD extension not found.\n");
+ #endif
+ }
+}
+
+void nxagentDisableXkbExtension(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisableXkbExtension: Called.\n");
+ #endif
+
+ if (nxagentXkbWrapper.base > 0)
+ {
+ if (nxagentXkbWrapper.ProcXkbDispatchBackup == NULL)
+ {
+ nxagentXkbWrapper.ProcXkbDispatchBackup = ProcVector[nxagentXkbWrapper.base];
+
+ ProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for ProcXkbDispatch.\n");
+ }
+ #endif
+
+ if (nxagentXkbWrapper.SProcXkbDispatchBackup == NULL)
+ {
+ nxagentXkbWrapper.SProcXkbDispatchBackup = SwappedProcVector[nxagentXkbWrapper.base];
+
+ SwappedProcVector[nxagentXkbWrapper.base] = ProcXkbInhibited;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentDisableXkbExtension: Nothing to be done for SProcXkbDispatch.\n");
+ }
+ #endif
+ }
+}
+
+void nxagentEnableXkbExtension(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentEnableXkbExtension: Called.\n");
+ #endif
+
+ if (nxagentXkbWrapper.base > 0)
+ {
+ if (nxagentXkbWrapper.ProcXkbDispatchBackup != NULL)
+ {
+ ProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.ProcXkbDispatchBackup;
+
+ nxagentXkbWrapper.ProcXkbDispatchBackup = NULL;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for ProcXkbDispatch.\n");
+ }
+ #endif
+
+ if (nxagentXkbWrapper.SProcXkbDispatchBackup != NULL)
+ {
+ SwappedProcVector[nxagentXkbWrapper.base] = nxagentXkbWrapper.SProcXkbDispatchBackup;
+
+ nxagentXkbWrapper.SProcXkbDispatchBackup = NULL;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentEnableXkbExtension: Nothing to be done for SProcXkbDispatch.\n");
+ }
+ #endif
+ }
+}
+
+void nxagentTuneXkbWrapper(void)
+{
+ if (nxagentOption(InhibitXkb) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTuneXkbWrapper: Nothing to do.\n");
+ #endif
+
+ return;
+ }
+
+ if (nxagentKeyboard != NULL &&
+ strcmp(nxagentKeyboard, "query") == 0)
+ {
+ nxagentDisableXkbExtension();
+ }
+ else
+ {
+ nxagentEnableXkbExtension();
+ }
+}
+
+static int nxagentXkbGetNames(char **rules, char **model, char **layout,
+ char **variant, char **options)
+{
+ Atom atom;
+ #ifdef _XSERVER64
+ Atom64 type;
+ #else
+ Atom type;
+ #endif
+ int format;
+ unsigned long n;
+ unsigned long after;
+ char *data;
+ char *name;
+ Status result;
+
+ data = name = NULL;
+
+ *rules = NULL;
+ *model = NULL;
+ *layout = NULL;
+ *variant = NULL;
+ *options = NULL;
+
+ atom = XInternAtom(nxagentDisplay, "_XKB_RULES_NAMES", 1);
+
+ if (atom == 0)
+ {
+ return 0;
+ }
+
+ result = XGetWindowProperty(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ atom, 0, 256, 0, XA_STRING, &type, &format,
+ &n, &after, (unsigned char **)&data);
+
+ if (result !=Success || data == NULL)
+ {
+ return 0;
+ }
+
+ if ((after > 0) || (type != XA_STRING) || (format != 8))
+ {
+ if (data != NULL)
+ {
+ XFree(data);
+ return 0;
+ }
+ }
+
+ name = data;
+
+ if (name < data + n)
+ {
+ *rules = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *model = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *layout = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *variant = name;
+ name += strlen(name) + 1;
+ }
+
+ if (name < data + n)
+ {
+ *options = name;
+ name += strlen(name) + 1;
+ }
+
+ return n;
+}
+
+void nxagentKeycodeConversionSetup(void)
+{
+ char *drules = NULL;
+ char *dmodel = NULL;
+ char *dlayout = NULL;
+ char *dvariant = NULL;
+ char *doptions = NULL;
+ unsigned int drulesLen;
+
+ nxagentKeycodeConversion = 0;
+
+ drulesLen = nxagentXkbGetNames(&drules, &dmodel, &dlayout,
+ &dvariant, &doptions);
+
+ #ifdef DEBUG
+ if (drulesLen != 0 && drules != NULL && dmodel != NULL)
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Remote: [rules='%s',model='%s',layout='%s',variant='%s',options='%s'].\n",
+ drules, dmodel, dlayout, dvariant, doptions);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Failed to retrieve remote rules.\n");
+ }
+ #endif
+
+ if (drulesLen != 0)
+ {
+ char *sessionpath = nxagentGetSessionPath();
+ if (sessionpath != NULL)
+ {
+ int keyboard_file_path_size = strlen(sessionpath) + strlen("/keyboard");
+ char *keyboard_file_path = malloc((keyboard_file_path_size + 1) * sizeof(char));
+ FILE *keyboard_file;
+ if (keyboard_file_path == NULL)
+ {
+ FatalError("nxagentKeycodeConversionSetup: malloc failed.");
+ }
+ strcpy(keyboard_file_path, sessionpath);
+ strcat(keyboard_file_path, "/keyboard");
+ if ((keyboard_file = fopen(keyboard_file_path, "w")) != NULL) {
+ if (drules != NULL)
+ fprintf(keyboard_file, "rules=\"%s\"\n", drules[0] == '\0' ? "," : drules);
+ if (dmodel != NULL)
+ fprintf(keyboard_file, "model=\"%s\"\n", dmodel[0] == '\0' ? "," : dmodel);
+ if (dlayout != NULL)
+ fprintf(keyboard_file, "layout=\"%s\"\n", dlayout[0] == '\0' ? "," : dlayout);
+ if (dvariant != NULL)
+ fprintf(keyboard_file, "variant=\"%s\"\n", dvariant[0] == '\0' ? "," : dvariant);
+ if (doptions != NULL)
+ fprintf(keyboard_file, "options=\"%s\"\n", doptions[0] == '\0' ? "," : doptions);
+ fclose(keyboard_file);
+ fprintf(stderr, "keyboard file created\n");
+ }
+ else
+ {
+ int save_err = errno;
+ fprintf(stderr, "keyboard file not created: %s\n", strerror(save_err));
+ }
+ free(keyboard_file_path);
+ }
+ else
+ {
+ fprintf(stderr, "SessionPath not defined\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr, "Failed to create the keyboard file\n");
+ }
+
+ if (drules != NULL && dmodel != NULL &&
+ (strcmp(drules, "evdev") == 0 ||
+ strcmp(dmodel, "evdev") == 0))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentKeycodeConversionSetup: "
+ "Activating KeyCode conversion.\n");
+ #endif
+
+ nxagentKeycodeConversion = 1;
+ }
+
+ if (drules != NULL)
+ {
+ XFree(drules);
+ }
+}
+
+void nxagentResetKeycodeConversion(void)
+{
+ int result;
+ XkbAgentInfoRec info;
+
+ result = XkbQueryExtension(nxagentDisplay, &info.Opcode, &info.EventBase,
+ &info.ErrorBase, &info.MajorVersion,
+ &info.MinorVersion);
+
+ if (result != 0)
+ {
+ nxagentKeycodeConversionSetup();
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentResetKeycodeConversion: "
+ "WARNING! Failed to query XKB extension.\n");
+ #endif
+
+ nxagentKeycodeConversion = 0;
+ }
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h
new file mode 100644
index 000000000..ba95a3a22
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keyboard.h
@@ -0,0 +1,135 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Keyboard_H__
+#define __Keyboard_H__
+
+#define NXAGENT_KEYBOARD_EVENT_MASK \
+ (KeyPressMask | KeyReleaseMask | FocusChangeMask | KeymapStateMask)
+
+#define NXAGENT_KEYBOARD_EXTENSION_EVENT_MASK \
+ (XkbStateNotifyMask)
+
+/*
+ * Queried at XKB initialization.
+ */
+
+typedef struct _XkbAgentInfo
+{
+ int Opcode;
+ int EventBase;
+ int ErrorBase;
+ int MajorVersion;
+ int MinorVersion;
+
+} XkbAgentInfoRec;
+
+extern XkbAgentInfoRec nxagentXkbInfo;
+
+typedef struct _XkbAgentState
+{
+ int Locked;
+ int Caps;
+ int Num;
+ int Focus;
+ int Initialized;
+
+} XkbAgentStateRec;
+
+extern XkbAgentStateRec nxagentXkbState;
+
+/*
+ * Info for enabling/disabling Xkb.
+ */
+
+typedef struct _XkbWrapper
+{
+ int base;
+ int eventBase;
+ int errorBase;
+ int (* ProcXkbDispatchBackup)(ClientPtr);
+ int (* SProcXkbDispatchBackup)(ClientPtr);
+
+} XkbWrapperRec;
+
+extern XkbWrapperRec nxagentXkbWrapper;
+
+extern char *nxagentKeyboard;
+
+/*
+ * Keyboard device procedure
+ * and utility functions.
+ */
+
+void nxagentBell(int volume, DeviceIntPtr pDev, void * ctrl, int cls);
+
+int nxagentKeyboardProc(DeviceIntPtr pDev, int onoff);
+
+void nxagentChangeKeyboardControl(DeviceIntPtr pDev, KeybdCtrl *ctrl);
+
+void nxagentNotifyKeyboardChanges(int oldMinKeycode, int oldMaxKeycode);
+
+int nxagentResetKeyboard(void);
+
+#ifdef XKB
+
+void nxagentInitXkbWrapper(void);
+
+void nxagentDisableXkbExtension(void);
+
+void nxagentEnableXkbExtension(void);
+
+void nxagentTuneXkbWrapper(void);
+
+void nxagentResetKeycodeConversion(void);
+
+#endif
+
+CARD8 nxagentConvertKeycode(CARD8 k);
+
+extern CARD8 nxagentCapsLockKeycode;
+extern CARD8 nxagentNumLockKeycode;
+
+extern unsigned int nxagentAltMetaMask;
+extern unsigned int nxagentAltMask;
+extern unsigned int nxagentMetaMask;
+extern unsigned int nxagentCapsMask;
+extern unsigned int nxagentNumlockMask;
+
+#endif /* __Keyboard_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
new file mode 100644
index 000000000..1e3ebca8f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.c
@@ -0,0 +1,662 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "X.h"
+#include "keysym.h"
+
+#include "screenint.h"
+#include "scrnintstr.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Events.h"
+#include "Options.h"
+#include "Keyboard.h"
+#include "Drawable.h"
+#include "Init.h" /* extern int nxagentX2go */
+#include "Utils.h"
+
+#include <unistd.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+extern Bool nxagentWMIsRunning;
+extern Bool nxagentIpaq;
+extern char *nxagentKeystrokeFile;
+
+#ifdef NX_DEBUG_INPUT
+int nxagentDebugInputDevices = False;
+unsigned long nxagentLastInputDevicesDumpTime = 0;
+extern void nxagentDeactivateInputDevicesGrabs();
+#endif
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/* must be included _after_ DUMP */
+#include "Keystroke.h"
+
+
+/* this table is used to parse actions given on the command line or in the
+ * config file, therefore indices have to match the enum in Keystroke.h */
+char * nxagentSpecialKeystrokeNames[] = {
+ "end_marker",
+ "close_session",
+ "switch_all_screens",
+ "fullscreen",
+ "minimize",
+ "defer",
+ "ignore",
+ "force_synchronization",
+
+#ifdef DEBUG_TREE
+ "debug_tree",
+#endif
+#ifdef DUMP
+ "regions_on_screen",
+#endif
+#ifdef NX_DEBUG_INPUT
+ "test_input",
+ "deactivate_input_devices_grab",
+#endif
+ "resize",
+ "viewport_move_left",
+ "viewport_move_up",
+ "viewport_move_right",
+ "viewport_move_down",
+ "viewport_scroll_left",
+ "viewport_scroll_up",
+ "viewport_scroll_right",
+ "viewport_scroll_down",
+
+ "reread_keystrokes",
+ NULL,
+};
+
+struct nxagentSpecialKeystrokeMap default_map[] = {
+ /* stroke, modifierMask, modifierAltMeta, keysym */
+#ifdef DEBUG_TREE
+ {KEYSTROKE_DEBUG_TREE, ControlMask, True, XK_q},
+#endif
+ {KEYSTROKE_CLOSE_SESSION, ControlMask, True, XK_t},
+ {KEYSTROKE_SWITCH_ALL_SCREENS, ControlMask, True, XK_f},
+ {KEYSTROKE_FULLSCREEN, ControlMask | ShiftMask, True, XK_f},
+ {KEYSTROKE_MINIMIZE, ControlMask, True, XK_m},
+ {KEYSTROKE_DEFER, ControlMask, True, XK_e},
+ {KEYSTROKE_IGNORE, ControlMask, True, XK_BackSpace},
+ {KEYSTROKE_IGNORE, 0, False, XK_Terminate_Server},
+ {KEYSTROKE_FORCE_SYNCHRONIZATION, ControlMask, True, XK_j},
+#ifdef DUMP
+ {KEYSTROKE_REGIONS_ON_SCREEN, ControlMask, True, XK_a},
+#endif
+#ifdef NX_DEBUG_INPUT
+ {KEYSTROKE_TEST_INPUT, ControlMask, True, XK_x},
+ {KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB, ControlMask, True, XK_y},
+#endif
+ {KEYSTROKE_RESIZE, ControlMask, True, XK_r},
+ {KEYSTROKE_VIEWPORT_MOVE_LEFT, ControlMask | ShiftMask, True, XK_Left},
+ {KEYSTROKE_VIEWPORT_MOVE_LEFT, ControlMask | ShiftMask, True, XK_KP_Left},
+ {KEYSTROKE_VIEWPORT_MOVE_UP, ControlMask | ShiftMask, True, XK_Up},
+ {KEYSTROKE_VIEWPORT_MOVE_UP, ControlMask | ShiftMask, True, XK_KP_Up},
+ {KEYSTROKE_VIEWPORT_MOVE_RIGHT, ControlMask | ShiftMask, True, XK_Right},
+ {KEYSTROKE_VIEWPORT_MOVE_RIGHT, ControlMask | ShiftMask, True, XK_KP_Right},
+ {KEYSTROKE_VIEWPORT_MOVE_DOWN, ControlMask | ShiftMask, True, XK_Down},
+ {KEYSTROKE_VIEWPORT_MOVE_DOWN, ControlMask | ShiftMask, True, XK_KP_Down},
+ {KEYSTROKE_VIEWPORT_SCROLL_LEFT, ControlMask, True, XK_Left},
+ {KEYSTROKE_VIEWPORT_SCROLL_LEFT, ControlMask, True, XK_KP_Left},
+ {KEYSTROKE_VIEWPORT_SCROLL_UP, ControlMask, True, XK_Up},
+ {KEYSTROKE_VIEWPORT_SCROLL_UP, ControlMask, True, XK_KP_Up},
+ {KEYSTROKE_VIEWPORT_SCROLL_RIGHT, ControlMask, True, XK_Right},
+ {KEYSTROKE_VIEWPORT_SCROLL_RIGHT, ControlMask, True, XK_KP_Right},
+ {KEYSTROKE_VIEWPORT_SCROLL_DOWN, ControlMask, True, XK_Down},
+ {KEYSTROKE_VIEWPORT_SCROLL_DOWN, ControlMask, True, XK_KP_Down},
+ {KEYSTROKE_REREAD_KEYSTROKES, ControlMask, True, XK_k},
+ {KEYSTROKE_END_MARKER, 0, False, NoSymbol},
+};
+struct nxagentSpecialKeystrokeMap *map = default_map;
+
+static Bool modifier_matches(unsigned int mask, int compare_alt_meta, unsigned int state)
+{
+ /* nxagentAltMetaMask needs special handling
+ * it seems to me its an and-ed mask of all possible meta and alt keys
+ * somehow...
+ *
+ * otherwise this function would be just a simple bitop
+ */
+ Bool ret = True;
+
+ if (compare_alt_meta) {
+ if (! (state & nxagentAltMetaMask)) {
+ ret = False;
+ }
+
+ mask &= ~nxagentAltMetaMask;
+ state &= ~nxagentAltMetaMask;
+ }
+
+ /* ignore CapsLock and/or Numlock if the keystroke does not
+ explicitly require them */
+
+ if ( !(mask & nxagentCapsMask) )
+ state &= ~nxagentCapsMask;
+
+ if ( !(mask & nxagentNumlockMask) )
+ state &= ~nxagentNumlockMask;
+
+ /* all modifiers except meta/alt have to match exactly, extra bits are evil */
+ if (mask != state) {
+ ret = False;
+ }
+
+ return ret;
+}
+
+static Bool read_binding_from_xmlnode(xmlNode *node, struct nxagentSpecialKeystrokeMap *ret)
+{
+ /* init the struct to have proper values in case not all attributes are found */
+ struct nxagentSpecialKeystrokeMap newkm = {
+ .stroke = KEYSTROKE_NOTHING,
+ .modifierMask = 0,
+ .modifierAltMeta = False,
+ .keysym = NoSymbol
+ };
+
+ for (xmlAttr *attr = node->properties; attr; attr = attr->next)
+ {
+ /* ignore attributes without data (which should never happen anyways) */
+ if (attr->children->content == NULL)
+ {
+ #ifdef DEBUG
+ char *aname = (attr->name)?((char *)attr->name):"unknown";
+ fprintf(stderr, "attribute %s with NULL value", aname);
+ #endif
+ continue;
+ }
+
+ if (strcmp((char *)attr->name, "action") == 0)
+ {
+ newkm.stroke = KEYSTROKE_NOTHING;
+ for (int i = 0; nxagentSpecialKeystrokeNames[i] != NULL; i++)
+ {
+ if (strcmp(nxagentSpecialKeystrokeNames[i], (char *)attr->children->content) == 0)
+ {
+ /* this relies on the values of enum nxagentSpecialKeystroke and the
+ * indices of nxagentSpecialKeystrokeNames being in sync */
+ newkm.stroke = i;
+ break;
+ }
+ }
+ if (newkm.stroke == KEYSTROKE_NOTHING)
+ fprintf(stderr, "Info: ignoring unknown keystroke action '%s'.\n", (char *)attr->children->content);
+ continue;
+ }
+ else if (strcmp((char *)attr->name, "key") == 0)
+ {
+ newkm.keysym = XStringToKeysym((char *)attr->children->content);
+ continue;
+ }
+ else
+ {
+ /* ignore attributes with value="0" or "false", everything else is interpreted as true */
+ if (strcmp((char *)attr->children->content, "0") == 0 || strcmp((char *)attr->children->content, "false") == 0)
+ continue;
+
+ if (strcmp((char *)attr->name, "Mod1") == 0) { newkm.modifierMask |= Mod1Mask; }
+ else if (strcmp((char *)attr->name, "Mod2") == 0) { newkm.modifierMask |= Mod2Mask; }
+ else if (strcmp((char *)attr->name, "Mod3") == 0) { newkm.modifierMask |= Mod3Mask; }
+ else if (strcmp((char *)attr->name, "Mod4") == 0) { newkm.modifierMask |= Mod4Mask; }
+ else if (strcmp((char *)attr->name, "Mod5") == 0) { newkm.modifierMask |= Mod5Mask; }
+ else if (strcmp((char *)attr->name, "Control") == 0) { newkm.modifierMask |= ControlMask; }
+ else if (strcmp((char *)attr->name, "Shift") == 0) { newkm.modifierMask |= ShiftMask; }
+ else if (strcmp((char *)attr->name, "Lock") == 0) { newkm.modifierMask |= LockMask; }
+ else if (strcmp((char *)attr->name, "AltMeta") == 0) { newkm.modifierAltMeta = True; }
+ }
+ }
+
+ if (newkm.stroke != KEYSTROKE_NOTHING && newkm.keysym != NoSymbol)
+ {
+ /* keysym and stroke are required, everything else is optional */
+ memcpy(ret, &newkm, sizeof(struct nxagentSpecialKeystrokeMap));
+ return True;
+ }
+ else
+ return False;
+}
+
+/*
+ * searches a keystroke xml file
+ *
+ * search order:
+ * - '-keystrokefile' commandline parameter
+ * - $NXAGENT_KEYSTROKEFILE environment variable
+ * - $HOME/.nx/config/keystrokes.cfg
+ * - /etc/nxagent/keystrokes.cfg
+ * - hardcoded traditional NX default settings
+ * If run in x2go flavour different filenames and varnames are used.
+ */
+void nxagentInitKeystrokes(Bool force)
+{
+ char *filename = NULL;
+
+ char *homefile;
+ char *etcfile;
+ char *envvar;
+
+ /* used for tracking if the config file parsing has already been
+ done (regardless of the result) */
+ static Bool done = False;
+
+ if (force) {
+ if (map != default_map)
+ {
+ free(map);
+ map = default_map;
+ }
+ fprintf(stderr, "Info: re-reading keystrokes configuration\n");
+ }
+ else
+ {
+ if (done)
+ return;
+ }
+
+ done = True;
+
+ if (nxagentX2go) {
+ homefile = "/.x2go/config/keystrokes.cfg";
+ etcfile = "/etc/x2go/keystrokes.cfg";
+ envvar = "X2GO_KEYSTROKEFILE";
+ } else {
+ homefile = "/.nx/config/keystrokes.cfg";
+ etcfile = "/etc/nxagent/keystrokes.cfg";
+ envvar = "NXAGENT_KEYSTROKEFILE";
+ }
+
+ if (nxagentKeystrokeFile && access(nxagentKeystrokeFile, R_OK) == 0)
+ {
+ if (!(filename = strdup(nxagentKeystrokeFile)))
+ {
+ fprintf(stderr, "malloc failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+ else if (nxagentKeystrokeFile)
+ {
+ fprintf(stderr, "Warning: Cannot read keystroke file '%s'.\n", nxagentKeystrokeFile);
+ if ((filename = getenv(envvar)) && access(filename, R_OK) == 0)
+ {
+ if (!(filename = strdup(filename)))
+ {
+ fprintf(stderr, "malloc failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ char *homedir = getenv("HOME");
+ filename = NULL;
+ if (homedir)
+ {
+ if (!(filename = calloc(1, strlen(homefile) + strlen(homedir) + 1)))
+ {
+ fprintf(stderr, "malloc failed");
+ exit(EXIT_FAILURE);
+ }
+ strcpy(filename, homedir);
+ strcpy(filename + strlen(homedir), homefile);
+ }
+
+ if (access(filename, R_OK) == 0)
+ {
+ /* empty */
+ }
+ else if (access(etcfile, R_OK) == 0)
+ {
+ free(filename);
+ if (!(filename = strdup(etcfile)))
+ {
+ fprintf(stderr, "malloc failed");
+ exit(EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ free(filename);
+ filename = NULL;
+ }
+ }
+ }
+
+ /* now we know which file to read, if any */
+ if (filename)
+ {
+ LIBXML_TEST_VERSION
+ xmlDoc *doc = xmlReadFile(filename, NULL, 0);
+ if (doc)
+ {
+ fprintf(stderr, "Info: using keystrokes file '%s'\n", filename);
+ for (xmlNode *cur = xmlDocGetRootElement(doc); cur; cur = cur->next)
+ {
+ if (cur->type == XML_ELEMENT_NODE && strcmp((char *)cur->name, "keystrokes") == 0)
+ {
+ xmlNode *bindings;
+ int num = 0;
+ int idx = 0;
+
+ for (bindings = cur->children; bindings; bindings = bindings->next)
+ {
+ if (bindings->type == XML_ELEMENT_NODE && strcmp((char *)bindings->name, "keystroke") == 0)
+ {
+ num++;
+ }
+ }
+ #ifdef DEBUG
+ fprintf(stderr, "%s: found %d keystrokes in %s\n", __func__, num, filename);
+ #endif
+ if (!(map = calloc(num+1, sizeof(struct nxagentSpecialKeystrokeMap))))
+ {
+ fprintf(stderr, "calloc failed");
+ exit(EXIT_FAILURE);
+ }
+
+ for (bindings = cur->children; bindings; bindings = bindings->next)
+ {
+ map[idx].stroke = KEYSTROKE_NOTHING;
+ if (bindings->type == XML_ELEMENT_NODE &&
+ strcmp((char *)bindings->name, "keystroke") == 0 &&
+ read_binding_from_xmlnode(bindings, &(map[idx])))
+ {
+ Bool store = True;
+ for (int j = 0; j < idx; j++)
+ {
+ if (map[j].stroke != KEYSTROKE_NOTHING &&
+ map[idx].keysym != NoSymbol &&
+ map[j].keysym == map[idx].keysym &&
+ map[j].modifierMask == map[idx].modifierMask &&
+ map[j].modifierAltMeta == map[idx].modifierAltMeta)
+ {
+ fprintf(stderr, "Warning: ignoring keystroke '%s' (already in use by '%s')\n",
+ nxagentSpecialKeystrokeNames[map[idx].stroke],
+ nxagentSpecialKeystrokeNames[map[j].stroke]);
+ store = False;
+ break;
+ }
+ }
+
+ if (store)
+ idx++;
+ else
+ map[idx].stroke = KEYSTROKE_NOTHING;
+ }
+ }
+ #ifdef DEBUG
+ fprintf(stderr, "%s: read %d keystrokes", __func__, idx);
+ #endif
+
+ map[idx].stroke = KEYSTROKE_END_MARKER;
+ }
+ }
+
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ }
+ else
+ {
+ fprintf(stderr, "Warning: could not read/parse keystrokes file '%s'\n", filename);
+ }
+ free(filename);
+ filename = NULL;
+ }
+
+ if (map == default_map)
+ {
+ fprintf(stderr, "Info: Using builtin keystrokes.\n");
+ }
+
+ nxagentDumpKeystrokes();
+}
+
+void nxagentDumpKeystrokes(void)
+{
+ int maxlen = 0;
+ for (int i = 0; nxagentSpecialKeystrokeNames[i]; i++)
+ maxlen = MAX(maxlen, strlen(nxagentSpecialKeystrokeNames[i]));
+
+ fprintf(stderr, "Current known keystrokes:\n");
+
+ for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) {
+ unsigned int mask = cur->modifierMask;
+ fprintf(stderr, " %-*s ", maxlen, nxagentSpecialKeystrokeNames[cur->stroke]);
+ if (mask & ControlMask) {fprintf(stderr, "Ctrl+"); mask &= ~ControlMask;}
+ if (mask & ShiftMask) {fprintf(stderr, "Shift+"); mask &= ~ShiftMask;}
+
+ /* these are only here for better readable modifier
+ names. Normally they are covered by the Mod<n> and Lock lines
+ below */
+ if (cur->modifierAltMeta) {fprintf(stderr, "Alt+"); mask &= ~(cur->modifierAltMeta);}
+ if (mask & nxagentCapsMask) {fprintf(stderr, "CapsLock+"); mask &= ~nxagentCapsMask;}
+ if (mask & nxagentNumlockMask) {fprintf(stderr, "NumLock+"); mask &= ~nxagentNumlockMask;}
+
+ if (mask & Mod1Mask) {fprintf(stderr, "Mod1+"); mask &= ~Mod1Mask;}
+ if (mask & Mod2Mask) {fprintf(stderr, "Mod2+"); mask &= ~Mod2Mask;}
+ if (mask & Mod3Mask) {fprintf(stderr, "Mod3+"); mask &= ~Mod3Mask;}
+ if (mask & Mod4Mask) {fprintf(stderr, "Mod4+"); mask &= ~Mod4Mask;}
+ if (mask & Mod5Mask) {fprintf(stderr, "Mod5+"); mask &= ~Mod5Mask;}
+ if (mask & LockMask) {fprintf(stderr, "Lock+"); mask &= ~LockMask;}
+ fprintf(stderr, "%s\n", XKeysymToString(cur->keysym));
+ }
+}
+
+static enum nxagentSpecialKeystroke find_keystroke(XKeyEvent *X)
+{
+ enum nxagentSpecialKeystroke ret = KEYSTROKE_NOTHING;
+
+ KeySym keysym = XKeycodeToKeysym(nxagentDisplay, X->keycode, 0);
+
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: got keysym '%c' (%d)\n", __func__, keysym, keysym);
+ #endif
+ for (struct nxagentSpecialKeystrokeMap *cur = map; cur->stroke != KEYSTROKE_END_MARKER; cur++) {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: checking keysym '%c' (%d)\n", __func__, cur->keysym, cur->keysym);
+ #endif
+ if (cur->keysym == keysym && modifier_matches(cur->modifierMask, cur->modifierAltMeta, X->state)) {
+ #ifdef DEBUG
+ fprintf(stderr, "%s: match including modifiers for keysym '%c' (%d), stroke %d (%s)\n", __func__, cur->keysym, cur->keysym, cur->stroke, nxagentSpecialKeystrokeNames[cur->stroke]);
+ #endif
+ return cur->stroke;
+ }
+ }
+
+ return ret;
+}
+
+Bool nxagentCheckSpecialKeystroke(XKeyEvent *X, enum HandleEventResult *result)
+{
+ enum nxagentSpecialKeystroke stroke = find_keystroke(X);
+ *result = doNothing;
+
+ #ifdef TEST
+ if (stroke != KEYSTROKE_NOTHING && stroke != KEYSTROKE_END_MARKER)
+ fprintf(stderr, "nxagentCheckSpecialKeystroke: got code %x - state %x - stroke %d (%s)\n",
+ X -> keycode, X -> state, stroke, nxagentSpecialKeystrokeNames[stroke]);
+ else
+ fprintf(stderr, "nxagentCheckSpecialKeystroke: got code %x - state %x - stroke %d (unused)\n",
+ X -> keycode, X -> state, stroke);
+ #endif
+
+ if (stroke == KEYSTROKE_NOTHING)
+ return False;
+
+ /*
+ * Check special keys.
+ */
+
+ /*
+ * FIXME: We should use the keysym instead that the keycode
+ * here.
+ */
+
+ if (X -> keycode == 130 && nxagentIpaq)
+ {
+ *result = doStartKbd;
+
+ return True;
+ }
+
+ switch (stroke) {
+#ifdef DEBUG_TREE
+ case KEYSTROKE_DEBUG_TREE:
+ *result = doDebugTree;
+ break;
+#endif
+ case KEYSTROKE_CLOSE_SESSION:
+ *result = doCloseSession;
+ break;
+ case KEYSTROKE_SWITCH_ALL_SCREENS:
+ if (!nxagentOption(Rootless)) {
+ *result = doSwitchAllScreens;
+ }
+ break;
+ case KEYSTROKE_MINIMIZE:
+ if (!nxagentOption(Rootless)) {
+ *result = doMinimize;
+ }
+ break;
+ case KEYSTROKE_DEFER:
+ *result = doSwitchDeferMode;
+ break;
+ case KEYSTROKE_IGNORE:
+ /* this is used e.g. to ignore C-A-Backspace aka XK_Terminate_Server */
+ return True;
+ break;
+ case KEYSTROKE_FORCE_SYNCHRONIZATION:
+ nxagentForceSynchronization = 1;
+ break;
+#ifdef DUMP
+ case KEYSTROKE_REGIONS_ON_SCREEN:
+ nxagentRegionsOnScreen();
+ break;
+#endif
+#ifdef NX_DEBUG_INPUT
+ case KEYSTROKE_TEST_INPUT:
+ /*
+ * Used to test the input devices state.
+ */
+ if (X -> type == KeyPress) {
+ if (!nxagentDebugInputDevices) {
+ fprintf(stderr, "Info: Turning input devices debug ON.\n");
+ nxagentDebugInputDevices = True;
+ } else {
+ fprintf(stderr, "Info: Turning input devices debug OFF.\n");
+ nxagentDebugInputDevices = False;
+ nxagentLastInputDevicesDumpTime = 0;
+ }
+ }
+ return True;
+ break;
+ case KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB:
+ if (X->type == KeyPress) {
+ nxagentDeactivateInputDevicesGrab();
+ }
+ return True;
+ break;
+#endif
+ case KEYSTROKE_FULLSCREEN:
+ if (!nxagentOption(Rootless)) {
+ *result = doSwitchFullscreen;
+ }
+ break;
+ case KEYSTROKE_RESIZE:
+ if (!nxagentOption(Rootless)) {
+ *result = doSwitchResizeMode;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_MOVE_LEFT:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportMoveLeft;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_MOVE_UP:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportMoveUp;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_MOVE_RIGHT:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportMoveRight;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_MOVE_DOWN:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportMoveDown;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_SCROLL_LEFT:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportLeft;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_SCROLL_UP:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportUp;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_SCROLL_RIGHT:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportRight;
+ }
+ break;
+ case KEYSTROKE_VIEWPORT_SCROLL_DOWN:
+ if (!nxagentOption(Rootless) && !nxagentOption(DesktopResize)) {
+ *result = doViewportDown;
+ }
+ break;
+ case KEYSTROKE_REREAD_KEYSTROKES:
+ /* two reasons to check on KeyRelease:
+ - this code is called for KeyPress and KeyRelease, so we
+ would read the keystroke file twice
+ - if the keystroke file changes settings for this key this
+ might lead to unexpected behaviour
+ */
+ if (X->type == KeyRelease)
+ nxagentInitKeystrokes(True);
+ break;
+ case KEYSTROKE_NOTHING: /* do nothing. difference to KEYSTROKE_IGNORE is the return value */
+ case KEYSTROKE_END_MARKER: /* just to make gcc STFU */
+ case KEYSTROKE_MAX:
+ break;
+ }
+ return (*result == doNothing);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
new file mode 100644
index 000000000..13a83d0fe
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Keystroke.h
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Keystroke_H__
+#define __Keystroke_H__
+
+#include "Events.h"
+
+extern Bool nxagentCheckSpecialKeystroke(XKeyEvent*, enum HandleEventResult*);
+extern void nxagentDumpKeystrokes(void);
+extern void nxagentInitKeystrokes(Bool force);
+
+/* keep this sorted, do not rely on any numerical value in this enum, and be aware
+ * that KEYSTROKE_MAX may be used in a malloc */
+
+/* also be aware that if changing any numerical values, you also need to change values
+ * Keystroke.c nxagentSpecialKeystrokeNames */
+enum nxagentSpecialKeystroke {
+ /* 0 is used as end marker */
+ KEYSTROKE_END_MARKER,
+ KEYSTROKE_CLOSE_SESSION,
+ KEYSTROKE_SWITCH_ALL_SCREENS,
+ KEYSTROKE_FULLSCREEN,
+ KEYSTROKE_MINIMIZE,
+ KEYSTROKE_DEFER,
+ KEYSTROKE_IGNORE,
+ KEYSTROKE_FORCE_SYNCHRONIZATION,
+
+ /* stuff used for debugging, probably not useful for most people */
+#ifdef DEBUG_TREE
+ KEYSTROKE_DEBUG_TREE,
+#endif
+#ifdef DUMP
+ KEYSTROKE_REGIONS_ON_SCREEN,
+#endif
+#ifdef NX_DEBUG_INPUT
+ KEYSTROKE_TEST_INPUT,
+ KEYSTROKE_DEACTIVATE_INPUT_DEVICES_GRAB,
+#endif
+
+ /* all the viewport stuff */
+ KEYSTROKE_RESIZE,
+ KEYSTROKE_VIEWPORT_MOVE_LEFT,
+ KEYSTROKE_VIEWPORT_MOVE_UP,
+ KEYSTROKE_VIEWPORT_MOVE_RIGHT,
+ KEYSTROKE_VIEWPORT_MOVE_DOWN,
+ KEYSTROKE_VIEWPORT_SCROLL_LEFT,
+ KEYSTROKE_VIEWPORT_SCROLL_UP,
+ KEYSTROKE_VIEWPORT_SCROLL_RIGHT,
+ KEYSTROKE_VIEWPORT_SCROLL_DOWN,
+
+ KEYSTROKE_REREAD_KEYSTROKES,
+
+ KEYSTROKE_NOTHING,
+
+ /* insert more here and in the string translation */
+
+ KEYSTROKE_MAX,
+};
+
+struct nxagentSpecialKeystrokeMap {
+ enum nxagentSpecialKeystroke stroke;
+ unsigned int modifierMask; /* everything except alt/meta */
+ Bool modifierAltMeta; /* modifier combination should include alt/meta */
+ KeySym keysym;
+};
+
+#endif /* __Keystroke_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Literals.h b/nx-X11/programs/Xserver/hw/nxagent/Literals.h
new file mode 100644
index 000000000..c0bb8c5d7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Literals.h
@@ -0,0 +1,213 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Simple table used to translate a request
+ * opcode to the name of the X request.
+ */
+
+static char *nxagentRequestLiteral[] =
+{
+ "None",
+ "CreateWindow",
+ "ChangeWindowAttributes",
+ "GetWindowAttributes",
+ "DestroyWindow",
+ "DestroySubwindows",
+ "ChangeSaveSet",
+ "ReparentWindow",
+ "MapWindow",
+ "MapSubwindows",
+ "UnmapWindow",
+ "UnmapSubwindows",
+ "ConfigureWindow",
+ "CirculateWindow",
+ "GetGeometry",
+ "QueryTree",
+ "InternAtom",
+ "GetAtomName",
+ "ChangeProperty",
+ "DeleteProperty",
+ "GetProperty",
+ "ListProperties",
+ "SetSelectionOwner",
+ "GetSelectionOwner",
+ "ConvertSelection",
+ "SendEvent",
+ "GrabPointer",
+ "UngrabPointer",
+ "GrabButton",
+ "UngrabButton",
+ "ChangeActivePointerGrab",
+ "GrabKeyboard",
+ "UngrabKeyboard",
+ "GrabKey",
+ "UngrabKey",
+ "AllowEvents",
+ "GrabServer",
+ "UngrabServer",
+ "QueryPointer",
+ "GetMotionEvents",
+ "TranslateCoords",
+ "WarpPointer",
+ "SetInputFocus",
+ "GetInputFocus",
+ "QueryKeymap",
+ "OpenFont",
+ "CloseFont",
+ "QueryFont",
+ "QueryTextExtents",
+ "ListFonts",
+ "ListFontsWithInfo",
+ "SetFontPath",
+ "GetFontPath",
+ "CreatePixmap",
+ "FreePixmap",
+ "CreateGC",
+ "ChangeGC",
+ "CopyGC",
+ "SetDashes",
+ "SetClipRectangles",
+ "FreeGC",
+ "ClearArea",
+ "CopyArea",
+ "CopyPlane",
+ "PolyPoint",
+ "PolyLine",
+ "PolySegment",
+ "PolyRectangle",
+ "PolyArc",
+ "FillPoly",
+ "PolyFillRectangle",
+ "PolyFillArc",
+ "PutImage",
+ "GetImage",
+ "PolyText8",
+ "PolyText16",
+ "ImageText8",
+ "ImageText16",
+ "CreateColormap",
+ "FreeColormap",
+ "CopyColormapAndFree",
+ "InstallColormap",
+ "UninstallColormap",
+ "ListInstalledColormaps",
+ "AllocColor",
+ "AllocNamedColor",
+ "AllocColorCells",
+ "AllocColorPlanes",
+ "FreeColors",
+ "StoreColors",
+ "StoreNamedColor",
+ "QueryColors",
+ "LookupColor",
+ "CreateCursor",
+ "CreateGlyphCursor",
+ "FreeCursor",
+ "RecolorCursor",
+ "QueryBestSize",
+ "QueryExtension",
+ "ListExtensions",
+ "ChangeKeyboardMapping",
+ "GetKeyboardMapping",
+ "ChangeKeyboardControl",
+ "GetKeyboardControl",
+ "Bell",
+ "ChangePointerControl",
+ "GetPointerControl",
+ "SetScreenSaver",
+ "GetScreenSaver",
+ "ChangeHosts",
+ "ListHosts",
+ "SetAccessControl",
+ "SetCloseDownMode",
+ "KillClient",
+ "RotateProperties",
+ "ForceScreenSaver",
+ "SetPointerMapping",
+ "GetPointerMapping",
+ "SetModifierMapping",
+ "GetModifierMapping",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "NoOperation"
+};
+
+static char *nxagentRenderRequestLiteral[] =
+{
+ "RenderQueryVersion",
+ "RenderQueryPictFormats",
+ "RenderQueryPictIndexValues",
+ "RenderQueryDithers",
+ "RenderCreatePicture",
+ "RenderChangePicture",
+ "RenderSetPictureClipRectangles",
+ "RenderFreePicture",
+ "RenderComposite",
+ "RenderScale",
+ "RenderTrapezoids",
+ "RenderTriangles",
+ "RenderTriStrip",
+ "RenderTriFan",
+ "RenderColorTrapezoids",
+ "RenderColorTriangles",
+ "RenderTransform",
+ "RenderCreateGlyphSet",
+ "RenderReferenceGlyphSet",
+ "RenderFreeGlyphSet",
+ "RenderAddGlyphs",
+ "RenderAddGlyphsFromPicture",
+ "RenderFreeGlyphs",
+ "RenderCompositeGlyphs",
+ "RenderCompositeGlyphs",
+ "RenderCompositeGlyphs",
+ "RenderFillRectangles",
+ "RenderCreateCursor",
+ "RenderSetPictureTransform",
+ "RenderQueryFilters",
+ "RenderSetPictureFilter",
+ "RenderCreateAnimCursor",
+ "RenderAddTraps",
+ "RenderCreateSolidFill",
+ "RenderCreateLinearGradient",
+ "RenderCreateRadialGradient",
+ "RenderCreateConicalGradient"
+};
+
+static char *nxagentShmRequestLiteral[] =
+{
+ "ShmQueryVersion",
+ "ShmAttach",
+ "ShmDetach",
+ "ShmPutImage",
+ "ShmGetImage",
+ "ShmCreatePixmap"
+};
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Millis.c b/nx-X11/programs/Xserver/hw/nxagent/Millis.c
new file mode 100644
index 000000000..ba801b62a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.c
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <time.h>
+#include <stdio.h>
+
+#include "Xos.h"
+#include "Millis.h"
+
+#ifdef DDXTIME
+
+CARD32 GetTimeInMillis()
+{
+ struct timeval ts;
+
+ X_GETTIMEOFDAY(&ts);
+
+ return(ts.tv_sec * 1000) + (ts.tv_usec / 1000);
+}
+
+#endif
+
+const char *GetTimeAsString()
+{
+ char *value;
+
+ struct timeval ts;
+
+ X_GETTIMEOFDAY(&ts);
+
+ value = ctime((time_t *) &ts.tv_sec);
+
+ *(value + strlen(value) - 1) = '\0';
+
+ return value;
+}
+
+const char *GetTimeInMillisAsString()
+{
+ char *value;
+
+ char tb[25];
+
+ struct timeval ts;
+
+ X_GETTIMEOFDAY(&ts);
+
+ value = ctime((time_t *) &ts.tv_sec);
+
+ sprintf(tb, "%.8s:%3.3f", value + 11,
+ (float) ts.tv_usec / 1000);
+
+ strncpy(value, tb, 24);
+
+ return value;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Millis.h b/nx-X11/programs/Xserver/hw/nxagent/Millis.h
new file mode 100644
index 000000000..1e76ccbfb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Millis.h
@@ -0,0 +1,38 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Millis_H__
+#define __Millis_H__
+
+#include "Xmd.h"
+
+CARD32 GetTimeInMillis(void);
+
+const char *GetTimeInMillisAsString(void);
+
+const char *GetTimeAsString(void);
+
+#endif /* __Millis_H__ */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c b/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c
new file mode 100644
index 000000000..ad02e13a8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXdamage.c
@@ -0,0 +1,225 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * $Id: damage.c,v 1.19 2005/10/06 21:55:41 anholt Exp $
+ *
+ * Copyright © 2003 Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#include "regionstr.h"
+#include "../../miext/damage/damage.h"
+#include <X11/fonts/font.h>
+
+/* prototypes */
+
+static int
+damageText (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned long count,
+ char *chars,
+ FontEncoding fontEncoding,
+ Bool textType);
+static int
+damagePolyText8(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars);
+static int
+damagePolyText16(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars);
+static void
+damageImageText8(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ char *chars);
+static void
+damageImageText16(DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ int count,
+ unsigned short *chars);
+
+#include "../../miext/damage/damage.c"
+
+static int
+damageText (DrawablePtr pDrawable,
+ GCPtr pGC,
+ int x,
+ int y,
+ unsigned long count,
+ char *chars,
+ FontEncoding fontEncoding,
+ Bool textType)
+{
+ CharInfoPtr *charinfo;
+ CharInfoPtr *info;
+ unsigned long i;
+ unsigned int n;
+ int w;
+ Bool imageblt;
+
+ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
+
+ charinfo = (CharInfoPtr *) malloc(count * sizeof(CharInfoPtr));
+ if (!charinfo)
+ return x;
+
+ GetGlyphs(pGC->font, count, (unsigned char *)chars,
+ fontEncoding, &i, charinfo);
+ n = (unsigned int)i;
+ w = 0;
+ if (!imageblt)
+ for (info = charinfo; i--; info++)
+ w += (*info)->metrics.characterWidth;
+
+ 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
+
+ }
+ free(charinfo);
+ return x + w;
+}
+
+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);
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c
new file mode 100644
index 000000000..5792a41c5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXdispatch.c
@@ -0,0 +1,1362 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 panoramix components contained the following notice */
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+
+#ifdef __sun
+#define False 0
+#define True 1
+#endif
+
+#include <X11/fonts/fontstruct.h>
+
+#define GC XlibGC
+#include <nx-X11/Xlib.h>
+#undef GC
+
+#include "../../dix/dispatch.c"
+
+#include "windowstr.h"
+
+#include "Atoms.h"
+#include "Splash.h"
+#include "Client.h"
+#include "Clipboard.h"
+#include "Reconnect.h"
+#include "Millis.h"
+#include "Font.h"
+#include <nx/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;
+
+#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
+
+#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, void *);
+
+
+void
+InitSelections()
+{
+ if (CurrentSelections)
+ free(CurrentSelections);
+ CurrentSelections = (Selection *)NULL;
+ NumCurrentSelections = 0;
+
+#ifdef NXAGENT_CLIPBOARD
+ {
+ Selection *newsels;
+ newsels = (Selection *)malloc(2 * sizeof(Selection));
+ if (!newsels)
+ return;
+ NumCurrentSelections += 2;
+ CurrentSelections = newsels;
+
+ CurrentSelections[0].selection = XA_PRIMARY;
+ CurrentSelections[0].lastTimeChanged = ClientTimeToServerTime(0);
+ CurrentSelections[0].window = screenInfo.screens[0]->root->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 = screenInfo.screens[0]->root->drawable.id;
+ CurrentSelections[1].pWin = NULL;
+ CurrentSelections[1].client = NullClient;
+ }
+#endif
+
+}
+
+#define MAJOROP ((xReq *)client->requestBuffer)->reqType
+
+void
+Dispatch(void)
+{
+ register int *clientReady; /* array of request ready clients */
+ register int result;
+ register ClientPtr client;
+ register int nready;
+ register HWEventQueuePtr* icheck = checkForInput;
+ long start_tick;
+
+ 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 *) malloc(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])
+ {
+ ProcessInputEvents();
+ 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;
+ saveAgentState("RUNNING");
+ }
+
+ #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
+
+ if (nready)
+ {
+ clientReady[0] = SmartScheduleClient (clientReady, nready);
+ nready = 1;
+ }
+ /*****************
+ * Handle events in round robin fashion, doing input between
+ * each round
+ *****************/
+
+ while (!dispatchException && (--nready >= 0))
+ {
+ client = clients[clientReady[nready]];
+ if (! client)
+ {
+ /* KillClient can cause this to happen */
+ continue;
+ }
+ /* GrabServer activation can cause this to be true */
+ if (grabState == GrabKickout)
+ {
+ grabState = GrabActive;
+ break;
+ }
+ isItTimeToYield = FALSE;
+
+ requestingClient = client;
+ start_tick = SmartScheduleTime;
+ while (!isItTimeToYield)
+ {
+ if (*icheck[0] != *icheck[1])
+ {
+ ProcessInputEvents();
+ FlushIfCriticalOutputPending();
+ }
+ if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
+ {
+ /* Penalize clients which consume ticks */
+ if (client->smart_priority > SMART_MIN_PRIORITY)
+ client->smart_priority--;
+ break;
+ }
+ /* 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)
+ {
+ if (result < 0)
+ 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
+ if ((client->requestLogIndex >= MAX_REQUEST_LOG) || (client->requestLogIndex <= 0))
+ client->requestLogIndex = 0;
+ client->requestLog[client->requestLogIndex] = MAJOROP;
+ client->requestLogIndex++;
+#endif
+ 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 (!SmartScheduleSignalEnable)
+ SmartScheduleTime = GetTimeInMillis();
+
+ if (result != Success)
+ {
+ if (client->noClientException != Success)
+ CloseDownClient(client);
+ else
+ SendErrorToClient(client, MAJOROP,
+ MinorOpcodeOfRequest(client),
+ client->errorValue, result);
+ break;
+ }
+#ifdef DAMAGEEXT
+ FlushIfCriticalOutputPending ();
+#endif
+ }
+ FlushAllOutput();
+ client = clients[clientReady[nready]];
+ if (client)
+ client->smart_stop_tick = SmartScheduleTime;
+ requestingClient = NULL;
+ }
+ dispatchException &= ~DE_PRIORITYCHANGE;
+ }
+#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());
+ saveAgentState("TERMINATING");
+
+ nxagentWaitDisplay();
+
+ fprintf(stderr, "Session: Session terminated at '%s'.\n", GetTimeAsString());
+ }
+
+ if (nxagentOption(Shadow) == 1)
+ {
+ NXShadowDestroy();
+ }
+ saveAgentState("TERMINATED");
+
+ KillAllClients();
+ free(clientReady);
+ dispatchException &= ~DE_RESET;
+}
+
+#undef MAJOROP
+
+int
+ProcReparentWindow(register ClientPtr client)
+{
+ register WindowPtr pWin, pParent;
+ REQUEST(xReparentWindowReq);
+ register int result;
+
+ REQUEST_SIZE_MATCH(xReparentWindowReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ DixWriteAccess);
+ if (!pWin)
+ return(BadWindow);
+
+ if (!nxagentWMPassed)
+ {
+ nxagentRemoveSplashWindow(pWin);
+ }
+
+ pParent = (WindowPtr)SecurityLookupWindow(stuff->parent, client,
+ DixWriteAccess);
+ if (!pParent)
+ return(BadWindow);
+ if (SAME_SCREENS(pWin->drawable, pParent->drawable))
+ {
+ if ((pWin->backgroundState == ParentRelative) &&
+ (pParent->drawable.depth != pWin->drawable.depth))
+ return BadMatch;
+ if ((pWin->drawable.class != InputOnly) &&
+ (pParent->drawable.class == InputOnly))
+ return BadMatch;
+ result = ReparentWindow(pWin, pParent,
+ (short)stuff->x, (short)stuff->y, client);
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+ return(result);
+ }
+ else
+ return (BadMatch);
+}
+
+
+int
+ProcQueryTree(register ClientPtr client)
+{
+ xQueryTreeReply reply;
+ int numChildren = 0;
+ register WindowPtr pChild, pWin, pHead;
+ Window *childIDs = (Window *)NULL;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client,
+ DixReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ memset(&reply, 0, sizeof(xQueryTreeReply));
+ reply.type = X_Reply;
+ reply.root = pWin->drawable.pScreen->root->drawable.id;
+ reply.sequenceNumber = client->sequence;
+ if (pWin->parent)
+ reply.parent = pWin->parent->drawable.id;
+ else
+ 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;
+
+ childIDs = (Window *) malloc(numChildren * sizeof(Window));
+ if (!childIDs)
+ return BadAlloc;
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
+ {
+ if (!IsViewportFrame(pChild))
+ {
+ childIDs[curChild++] = pChild->drawable.id;
+ }
+ }
+ }
+
+ reply.nChildren = numChildren;
+ reply.length = (numChildren * sizeof(Window)) >> 2;
+
+ WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
+ if (numChildren)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, numChildren * sizeof(Window), childIDs);
+ free(childIDs);
+ }
+
+ return(client->noClientException);
+}
+
+
+int
+ProcSetSelectionOwner(register ClientPtr client)
+{
+ WindowPtr pWin;
+ TimeStamp time;
+ REQUEST(xSetSelectionOwnerReq);
+
+ REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);
+ UpdateCurrentTime();
+ time = ClientTimeToServerTime(stuff->time);
+
+ /* If the client's time stamp is in the future relative to the server's
+ time stamp, do not set the selection, just return success. */
+ if (CompareTimeStamps(time, currentTime) == LATER)
+ return Success;
+ if (stuff->window != None)
+ {
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ DixReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ }
+ else
+ pWin = (WindowPtr)None;
+ if (ValidAtom(stuff->selection))
+ {
+ int i = 0;
+
+ /*
+ * First, see if the selection is already set...
+ */
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection)
+ i++;
+ if (i < NumCurrentSelections)
+ {
+ xEvent event;
+
+ /* If the timestamp in client's request is in the past relative
+ to the time stamp indicating the last time the owner of the
+ selection was set, do not set the selection, just return
+ success. */
+ if (CompareTimeStamps(time, CurrentSelections[i].lastTimeChanged)
+ == EARLIER)
+ return Success;
+ if (CurrentSelections[i].client &&
+ (!pWin || (CurrentSelections[i].client != client)))
+ {
+ event.u.u.type = SelectionClear;
+ event.u.selectionClear.time = time.milliseconds;
+ event.u.selectionClear.window = CurrentSelections[i].window;
+ event.u.selectionClear.atom = CurrentSelections[i].selection;
+ (void) TryClientEvents (CurrentSelections[i].client, &event, 1,
+ NoEventMask, NoEventMask /* CantBeFiltered */,
+ NullGrab);
+ }
+ }
+ else
+ {
+ /*
+ * It doesn't exist, so add it...
+ */
+ Selection *newsels;
+
+ if (i == 0)
+ newsels = (Selection *)malloc(sizeof(Selection));
+ else
+ newsels = (Selection *)realloc(CurrentSelections,
+ (NumCurrentSelections + 1) * sizeof(Selection));
+ if (!newsels)
+ return BadAlloc;
+ NumCurrentSelections++;
+ CurrentSelections = newsels;
+ CurrentSelections[i].selection = stuff->selection;
+ }
+ CurrentSelections[i].lastTimeChanged = time;
+ CurrentSelections[i].window = stuff->window;
+ CurrentSelections[i].pWin = pWin;
+ CurrentSelections[i].client = (pWin ? client : NullClient);
+ if (SelectionCallback)
+ {
+ SelectionInfoRec info;
+
+ info.selection = &CurrentSelections[i];
+ 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
+ {
+ client->errorValue = stuff->selection;
+ return (BadAtom);
+ }
+}
+
+
+int
+ProcConvertSelection(register ClientPtr client)
+{
+ Bool paramsOkay;
+ xEvent event;
+ WindowPtr pWin;
+ REQUEST(xConvertSelectionReq);
+
+ REQUEST_SIZE_MATCH(xConvertSelectionReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->requestor, client,
+ DixReadAccess);
+ 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);
+ if (paramsOkay)
+ {
+ int i;
+
+ i = 0;
+ while ((i < NumCurrentSelections) &&
+ CurrentSelections[i].selection != stuff->selection) i++;
+ if ((i < NumCurrentSelections) &&
+ (CurrentSelections[i].window != None) && (CurrentSelections[i].client != NullClient)
+#ifdef XCSECURITY
+ && (!client->CheckAccess ||
+ (* client->CheckAccess)(client, CurrentSelections[i].window,
+ RT_WINDOW, DixReadAccess,
+ CurrentSelections[i].pWin))
+#endif
+ )
+
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = SelectionRequest;
+ event.u.selectionRequest.time = stuff->time;
+ event.u.selectionRequest.owner =
+ CurrentSelections[i].window;
+ event.u.selectionRequest.requestor = stuff->requestor;
+ event.u.selectionRequest.selection = stuff->selection;
+ event.u.selectionRequest.target = stuff->target;
+ event.u.selectionRequest.property = stuff->property;
+ if (TryClientEvents(
+ CurrentSelections[i].client, &event, 1, NoEventMask,
+ NoEventMask /* CantBeFiltered */, NullGrab))
+ return (client->noClientException);
+ }
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = SelectionNotify;
+ event.u.selectionNotify.time = stuff->time;
+ event.u.selectionNotify.requestor = stuff->requestor;
+ event.u.selectionNotify.selection = stuff->selection;
+ event.u.selectionNotify.target = stuff->target;
+ event.u.selectionNotify.property = None;
+ (void) TryClientEvents(client, &event, 1, NoEventMask,
+ NoEventMask /* CantBeFiltered */, NullGrab);
+ return (client->noClientException);
+ }
+ else
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+}
+
+
+int
+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)
+ {
+ return(client->noClientException);
+ }
+ else
+ return err;
+}
+
+int
+ProcCloseFont(register ClientPtr client)
+{
+ FontPtr pFont;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
+ DixDestroyAccess);
+ 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);
+ }
+ else
+ {
+ client->errorValue = stuff->id;
+ return (BadFont);
+ }
+}
+
+
+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);
+}
+
+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);
+}
+
+
+int
+ProcFreePixmap(register ClientPtr client)
+{
+ PixmapPtr pMap;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ pMap = (PixmapPtr)SecurityLookupIDByType(client, stuff->id, RT_PIXMAP,
+ DixDestroyAccess);
+ 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);
+ }
+ else
+ {
+ client->errorValue = stuff->id;
+ return (BadPixmap);
+ }
+}
+
+
+int
+ProcSetScreenSaver (register ClientPtr client)
+{
+ int blankingOption, exposureOption;
+ REQUEST(xSetScreenSaverReq);
+
+ REQUEST_SIZE_MATCH(xSetScreenSaverReq);
+ blankingOption = stuff->preferBlank;
+ if ((blankingOption != DontPreferBlanking) &&
+ (blankingOption != PreferBlanking) &&
+ (blankingOption != DefaultBlanking))
+ {
+ client->errorValue = blankingOption;
+ return BadValue;
+ }
+ exposureOption = stuff->allowExpose;
+ if ((exposureOption != DontAllowExposures) &&
+ (exposureOption != AllowExposures) &&
+ (exposureOption != DefaultExposures))
+ {
+ client->errorValue = exposureOption;
+ return BadValue;
+ }
+ if (stuff->timeout < -1)
+ {
+ client->errorValue = stuff->timeout;
+ return BadValue;
+ }
+ if (stuff->interval < -1)
+ {
+ client->errorValue = stuff->interval;
+ return BadValue;
+ }
+
+ /*
+ * 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
+ {
+ ScreenSaverBlanking = blankingOption;
+ }
+
+ if (exposureOption == DefaultExposures)
+ {
+ ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
+ }
+ 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
+
+ else
+ {
+ fprintf(stderr, "ProcSetScreenSaver: Keeping auto-disconnect timeout set to [%d] seconds.\n",
+ nxagentOption(Timeout));
+ }
+
+ #endif
+
+ return (client->noClientException);
+}
+
+
+int ProcForceScreenSaver(register ClientPtr client)
+{
+ REQUEST(xForceScreenSaverReq);
+
+ REQUEST_SIZE_MATCH(xForceScreenSaverReq);
+
+ if ((stuff->mode != ScreenSaverReset) &&
+ (stuff->mode != ScreenSaverActive))
+ {
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+
+ /*
+ * 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;
+}
+
+
+/**********************
+ * CloseDownClient
+ *
+ * Client can either mark his resources destroy or retain. If retained and
+ * then killed again, the client is really destroyed.
+ *********************/
+
+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 */
+ if (grabState != GrabNone && grabClient == client)
+ {
+ UngrabServer(client);
+ }
+ BITCLEAR(grabWaiters, client->index);
+ DeleteClientFromAnySelections(client);
+ ReleaseActiveGrabs(client);
+ DeleteClientFontStuff(client);
+ if (!really_close_down)
+ {
+ /* This frees resources that should never be retained
+ * no matter what the close down mode is. Actually we
+ * could do this unconditionally, but it's probably
+ * better not to traverse all the client's resources
+ * twice (once here, once a few lines down in
+ * FreeClientResources) in the common case of
+ * really_close_down == TRUE.
+ */
+ FreeClientNeverRetainResources(client);
+ client->clientState = ClientStateRetained;
+ if (ClientStateCallback)
+ {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = (xConnSetupPrefix *)NULL;
+ clientinfo.setup = (xConnSetup *) NULL;
+ CallCallbacks((&ClientStateCallback), (void *)&clientinfo);
+ }
+ }
+ client->clientGone = TRUE; /* so events aren't sent to client */
+ if (ClientIsAsleep(client))
+ ClientSignal (client);
+ ProcessWorkQueueZombies();
+ CloseDownConnection(client);
+
+ /* If the client made it to the Running stage, nClients has
+ * been incremented on its behalf, so we need to decrement it
+ * now. If it hasn't gotten to Running, nClients has *not*
+ * been incremented, so *don't* decrement it.
+ */
+ if (client->clientState != ClientStateInitial &&
+ client->clientState != ClientStateAuthenticating )
+ {
+ --nClients;
+ }
+ }
+
+ if (really_close_down)
+ {
+ if (client->clientState == ClientStateRunning && nClients == 0)
+ dispatchException |= dispatchExceptionAtReset;
+
+ client->clientState = ClientStateGone;
+ if (ClientStateCallback)
+ {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = (xConnSetupPrefix *)NULL;
+ clientinfo.setup = (xConnSetup *) NULL;
+ CallCallbacks((&ClientStateCallback), (void *)&clientinfo);
+ }
+ FreeClientResources(client);
+ if (client->index < nextFreeClientID)
+ nextFreeClientID = client->index;
+ clients[client->index] = NullClient;
+ SmartLastClient = NullClient;
+ free(client);
+
+ while (!clients[currentMaxClients-1])
+ currentMaxClients--;
+ }
+}
+
+int
+InitClientPrivates(ClientPtr client)
+{
+ register char *ptr;
+ DevUnion *ppriv;
+ register unsigned *sizes;
+ register unsigned size;
+ register int i;
+
+ if (totalClientSize == sizeof(ClientRec))
+ ppriv = (DevUnion *)NULL;
+ else if (client->index)
+ ppriv = (DevUnion *)(client + 1);
+ else
+ {
+ ppriv = (DevUnion *)malloc(totalClientSize - sizeof(ClientRec));
+ if (!ppriv)
+ return 0;
+ }
+ client->devPrivates = ppriv;
+ sizes = clientPrivateSizes;
+ ptr = (char *)(ppriv + clientPrivateLen);
+ for (i = clientPrivateLen; --i >= 0; ppriv++, sizes++)
+ {
+ if ( (size = *sizes) )
+ {
+ ppriv->ptr = (void *)ptr;
+ ptr += size;
+ }
+ else
+ ppriv->ptr = (void *)NULL;
+ }
+
+ /*
+ * Initialize the private members.
+ */
+
+ nxagentInitClientPrivates(client);
+
+ return 1;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c
new file mode 100644
index 000000000..49d864887
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c
@@ -0,0 +1,1543 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************************
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 panoramix components contained the following notice */
+/*
+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.
+
+******************************************************************/
+
+#include "dixstruct.h"
+#include "dixfontstr.h"
+
+static Bool doOpenFont(ClientPtr client, OFclosurePtr c);
+static Bool doListFontsAndAliases(ClientPtr client, LFclosurePtr c);
+
+#include "../../dix/dixfonts.c"
+
+/*
+#define NXAGENT_DEBUG
+*/
+
+#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
+
+static Bool
+doOpenFont(ClientPtr client, OFclosurePtr c)
+{
+ FontPtr pfont = NullFont;
+ FontPathElementPtr fpe = NULL;
+ ScreenPtr pScr;
+ int err = Successful;
+ int i;
+ char *alias,
+ *newname;
+ int newlen;
+ int aliascount = 20;
+ char nxagentOrigFontName[256];
+ int nxagentOrigFontNameLen;
+
+ /*
+ * Decide at runtime what FontFormat to use.
+ */
+ Mask FontFormat =
+
+ ((screenInfo.imageByteOrder == LSBFirst) ?
+ BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
+
+ ((screenInfo.bitmapBitOrder == LSBFirst) ?
+ BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
+
+ BitmapFormatImageRectMin |
+
+#if GLYPHPADBYTES == 1
+ BitmapFormatScanlinePad8 |
+#endif
+
+#if GLYPHPADBYTES == 2
+ BitmapFormatScanlinePad16 |
+#endif
+
+#if GLYPHPADBYTES == 4
+ BitmapFormatScanlinePad32 |
+#endif
+
+#if GLYPHPADBYTES == 8
+ BitmapFormatScanlinePad64 |
+#endif
+
+ 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)
+ {
+ fpe = c->fpe_list[c->current_fpe];
+#ifdef HAS_XFONT2
+ (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
+#else
+ (*fpe_functions[fpe->type].client_died) ((void *) client, fpe);
+#endif /* HAS_XFONT2 */
+ }
+ err = Successful;
+ goto bail;
+ }
+ while (c->current_fpe < c->num_fpes) {
+ fpe = c->fpe_list[c->current_fpe];
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->open_font)
+#else
+ err = (*fpe_functions[fpe->type].open_font)
+#endif /* HAS_XFONT2 */
+ ((void *) client, fpe, c->flags,
+ c->fontname, c->fnamelen, FontFormat,
+ BitmapFormatMaskByte |
+ BitmapFormatMaskBit |
+ BitmapFormatMaskImageRectangle |
+ BitmapFormatMaskScanLinePad |
+ BitmapFormatMaskScanLineUnit,
+ c->fontid, &pfont, &alias,
+ c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
+ c->non_cachable_font :
+ (FontPtr)0);
+
+ if (err == FontNameAlias && alias) {
+ newlen = strlen(alias);
+ newname = (char *) realloc(c->fontname, newlen);
+ if (!newname) {
+ err = AllocError;
+ break;
+ }
+ memmove(newname, alias, newlen);
+ c->fontname = newname;
+ c->fnamelen = newlen;
+ c->current_fpe = 0;
+ if (--aliascount <= 0)
+ break;
+ continue;
+ }
+ if (err == BadFontName) {
+ c->current_fpe++;
+ continue;
+ }
+ if (err == Suspended) {
+ if (!c->slept) {
+ c->slept = TRUE;
+ ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (void *) c);
+#ifdef NXAGENT_DEBUG
+ fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client);
+#endif
+ }
+ return TRUE;
+ }
+ break;
+ }
+
+ if (err != Successful)
+ goto bail;
+ if (!pfont) {
+ err = BadFontName;
+ goto bail;
+ }
+ /* check values for firstCol, lastCol, firstRow, and lastRow */
+ if (pfont->info.firstCol > pfont->info.lastCol ||
+ pfont->info.firstRow > pfont->info.lastRow ||
+ pfont->info.lastCol - pfont->info.firstCol > 255) {
+ err = AllocError;
+ goto bail;
+ }
+ if (!pfont->fpe)
+ pfont->fpe = fpe;
+ pfont->refcnt++;
+ if (pfont->refcnt == 1) {
+ UseFPE(pfont->fpe);
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScr = screenInfo.screens[i];
+ if (pScr->RealizeFont)
+ {
+
+ /* 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=BadFontName;
+ goto bail;
+ }
+ }
+ }
+ }
+ if (!AddResource(c->fontid, RT_FONT, (void *) pfont)) {
+ 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, (void *) pfont)) {
+ FreeResource(c->fontid, RT_NONE);
+ err = AllocError;
+ goto bail;
+ }
+ }
+ if (patternCache && pfont != c->non_cachable_font)
+#ifdef HAS_XFONT2
+ xfont2_cache_font_pattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen,
+#else
+ CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen,
+#endif /* HAS_XFONT2 */
+ pfont);
+bail:
+ if (err != Successful && c->client != serverClient) {
+ SendErrorToClient(c->client, X_OpenFont, 0,
+ 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]);
+ }
+ free(c->fpe_list);
+ free(c->fontname);
+ free(c);
+ return TRUE;
+}
+
+
+static Bool
+doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
+{
+ FontPathElementPtr fpe;
+ int err = Successful;
+ FontNamesPtr names = NULL;
+ char *name, *resolved=NULL;
+ int namelen, resolvedlen;
+ int nnames;
+ int stringLens;
+ int i;
+ xListFontsReply reply;
+ char *bufptr;
+ char *bufferStart;
+ int aliascount = 0;
+
+ if (client->clientGone)
+ {
+ if (c->current.current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current.current_fpe];
+#ifdef HAS_XFONT2
+ (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
+#else
+ (*fpe_functions[fpe->type].client_died) ((void *) client, fpe);
+#endif /* HAS_XFONT2 */
+ }
+ 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;
+
+#ifdef HAS_XFONT2
+ if (!fpe_functions[fpe->type]->start_list_fonts_and_aliases)
+#else
+ if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
+#endif /* HAS_XFONT2 */
+ {
+ /* This FPE doesn't support/require list_fonts_and_aliases */
+
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->list_fonts)
+#else
+ err = (*fpe_functions[fpe->type].list_fonts)
+#endif /* HAS_XFONT2 */
+ ((void *) 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)doListFontsAndAliases,
+ (void *) c);
+#ifdef NXAGENT_DEBUG
+ fprintf(stderr, " NXdixfonts: doListFont (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) {
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->start_list_fonts_and_aliases)
+#else
+ err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
+#endif /* HAS_XFONT2 */
+ ((void *) 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)doListFontsAndAliases,
+ (void *) c);
+ c->slept = TRUE;
+ }
+ return TRUE;
+ }
+ if (err == Successful)
+ c->current.list_started = TRUE;
+ }
+ if (err == Successful) {
+ char *tmpname;
+ name = 0;
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->list_next_font_or_alias)
+#else
+ err = (*fpe_functions[fpe->type].list_next_font_or_alias)
+#endif /* HAS_XFONT2 */
+ ((void *) c->client, fpe, &name, &namelen, &tmpname,
+ &resolvedlen, c->current.private);
+ if (err == Suspended) {
+ if (!c->slept) {
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (void *) 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;
+ }
+ if (err == FontNameAlias) {
+ if (resolved) free(resolved);
+ resolved = (char *) malloc(resolvedlen + 1);
+ if (resolved)
+ memmove(resolved, tmpname, resolvedlen + 1);
+ }
+ }
+
+ if (err == Successful)
+ {
+ if (c->haveSaved)
+ {
+ if (c->savedName)
+#ifdef HAS_XFONT2
+ (void)xfont2_add_font_names_name(c->names, c->savedName,
+#else
+ (void)AddFontNamesName(c->names, c->savedName,
+#endif /* HAS_XFONT2 */
+ c->savedNameLen);
+ }
+ else
+#ifdef HAS_XFONT2
+ (void)xfont2_add_font_names_name(c->names, name, namelen);
+#else
+ (void)AddFontNamesName(c->names, name, namelen);
+#endif /* HAS_XFONT2 */
+ }
+
+ /*
+ * 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;
+#ifdef HAS_XFONT2
+ (void) (*fpe_functions[fpe->type]->list_next_font_or_alias)
+#else
+ (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
+#endif /* HAS_XFONT2 */
+ ((void *) 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)
+ free(c->savedName);
+ c->savedName = (char *)malloc(namelen + 1);
+ if (c->savedName)
+ memmove(c->savedName, name, namelen + 1);
+ 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
+ */
+ if (err != Successful) {
+ SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
+ goto bail;
+ }
+
+finish:
+
+ names = c->names;
+ nnames = names->nnames;
+ client = c->client;
+ stringLens = 0;
+ for (i = 0; i < nnames; i++)
+ stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
+
+ memset(&reply, 0, sizeof(xListFontsReply));
+ reply.type = X_Reply;
+ reply.length = (stringLens + nnames + 3) >> 2;
+ reply.nFonts = nnames;
+ reply.sequenceNumber = client->sequence;
+
+ bufptr = bufferStart = (char *) malloc(reply.length << 2);
+
+ if (!bufptr && reply.length) {
+ SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
+ goto bail;
+ }
+ /*
+ * since WriteToClient long word aligns things, copy to temp buffer and
+ * write all at once
+ */
+ for (i = 0; i < nnames; i++) {
+ if (names->length[i] > 255)
+ 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];
+ }
+ }
+ nnames = reply.nFonts;
+ reply.length = (stringLens + nnames + 3) >> 2;
+ client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
+ WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
+ WriteToClient(client, stringLens + nnames, bufferStart);
+ free(bufferStart);
+
+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]);
+ free(c->fpe_list);
+ if (c->savedName) free(c->savedName);
+#ifdef HAS_XFONT2
+ xfont2_free_font_names(names);
+#else
+ FreeFontNames(names);
+#endif /* HAS_XFONT2 */
+ free(c);
+ if (resolved) free(resolved);
+ return TRUE;
+}
+
+int
+ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
+ unsigned max_names)
+{
+ int i;
+ LFclosurePtr c;
+
+ /*
+ * The right error to return here would be BadName, however the
+ * specification does not allow for a Name error on this request.
+ * Perhaps a better solution would be to return a nil list, i.e.
+ * a list containing zero fontnames.
+ */
+ if (length > XLFDMAXFONTNAMELEN)
+ return BadAlloc;
+
+ if (!(c = (LFclosurePtr) malloc(sizeof *c)))
+ return BadAlloc;
+ c->fpe_list = (FontPathElementPtr *)
+ malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ free(c);
+ return BadAlloc;
+ }
+#ifdef HAS_XFONT2
+ c->names = xfont2_make_font_names_record(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames);
+#else
+ c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames);
+#endif /* HAS_XFONT2 */
+ if (!c->names)
+ {
+ free(c->fpe_list);
+ free(c);
+ return BadAlloc;
+ }
+ memmove( c->current.pattern, pattern, length);
+ 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 = length;
+ c->current.current_fpe = 0;
+ c->current.max_names = max_names;
+ c->current.list_started = FALSE;
+ c->current.private = 0;
+ c->haveSaved = FALSE;
+ c->slept = FALSE;
+ c->savedName = 0;
+ doListFontsAndAliases(client, c);
+ return Success;
+}
+
+int
+doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
+{
+ FontPathElementPtr fpe;
+ int err = Successful;
+ char *name;
+ int namelen;
+ int numFonts;
+ FontInfoRec fontInfo,
+ *pFontInfo;
+ xListFontsWithInfoReply *reply;
+ int length;
+ xFontProp *pFP;
+ int i;
+ int aliascount = 0;
+ xListFontsWithInfoReply finalReply;
+
+ if (client->clientGone)
+ {
+ if (c->current.current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current.current_fpe];
+#ifdef HAS_XFONT2
+ (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
+#else
+ (*fpe_functions[fpe->type].client_died) ((void *) client, fpe);
+#endif /* HAS_XFONT2 */
+ }
+ err = Successful;
+ goto bail;
+ }
+ client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
+ 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 (!c->current.list_started)
+ {
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->start_list_fonts_with_info)
+#else
+ err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
+#endif /* HAS_XFONT2 */
+ (client, fpe, c->current.pattern, c->current.patlen,
+ c->current.max_names, &c->current.private);
+ if (err == Suspended)
+ {
+ if (!c->slept)
+ {
+ ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
+ c->slept = TRUE;
+#ifdef NXAGENT_DEBUG
+ fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client);
+#endif
+ }
+ return TRUE;
+ }
+ if (err == Successful)
+ c->current.list_started = TRUE;
+ }
+ if (err == Successful)
+ {
+ name = 0;
+ pFontInfo = &fontInfo;
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->list_next_font_with_info)
+#else
+ err = (*fpe_functions[fpe->type].list_next_font_with_info)
+#endif /* HAS_XFONT2 */
+ (client, fpe, &name, &namelen, &pFontInfo,
+ &numFonts, c->current.private);
+ if (err == Suspended)
+ {
+ if (!c->slept)
+ {
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsWithInfo,
+ c);
+ c->slept = TRUE;
+#ifdef NXAGENT_DEBUG
+ fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client);
+#endif
+ }
+ return TRUE;
+ }
+ }
+ /*
+ * 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
+ */
+ if (err == FontNameAlias)
+ {
+ /*
+ * 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.
+ */
+ if (c->haveSaved)
+ {
+ char *tmpname;
+ int tmpnamelen;
+ FontInfoPtr tmpFontInfo;
+
+ tmpname = 0;
+ tmpFontInfo = &fontInfo;
+#ifdef HAS_XFONT2
+ (void) (*fpe_functions[fpe->type]->list_next_font_with_info)
+#else
+ (void) (*fpe_functions[fpe->type].list_next_font_with_info)
+#endif /* HAS_XFONT2 */
+ (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
+ &numFonts, c->current.private);
+ if (--aliascount <= 0)
+ {
+ err = BadFontName;
+ goto ContBadFontName;
+ }
+ }
+ else
+ {
+ c->saved = c->current;
+ c->haveSaved = TRUE;
+ c->savedNumFonts = numFonts;
+ if (c->savedName)
+ free(c->savedName);
+ c->savedName = (char *)malloc(namelen + 1);
+ if (c->savedName)
+ memmove(c->savedName, name, namelen + 1);
+ aliascount = 20;
+ }
+ memmove(c->current.pattern, name, namelen);
+ c->current.patlen = namelen;
+ c->current.max_names = 1;
+ c->current.current_fpe = 0;
+ c->current.private = 0;
+ c->current.list_started = FALSE;
+ }
+ /*
+ * At the end of this FPE, step to the next. If we've finished
+ * processing an alias, pop state back. If we've sent enough font
+ * names, quit. Always wait for BadFontName to let the FPE
+ * have a chance to clean up.
+ */
+ else if (err == BadFontName)
+ {
+ ContBadFontName: ;
+ c->current.list_started = FALSE;
+ c->current.current_fpe++;
+ err = Successful;
+ if (c->haveSaved)
+ {
+ if (c->current.max_names == 0 ||
+ c->current.current_fpe == c->num_fpes)
+ {
+ c->haveSaved = FALSE;
+ c->saved.max_names -= (1 - c->current.max_names);
+ c->current = c->saved;
+ }
+ }
+ else if (c->current.max_names == 0)
+ break;
+ }
+ 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)
+ {
+ reply = (xListFontsWithInfoReply *) realloc(c->reply, length);
+ if (!reply)
+ {
+ err = AllocError;
+ break;
+ }
+ memset(reply + c->length, 0, length - c->length);
+ c->reply = reply;
+ c->length = length;
+ }
+ reply->type = X_Reply;
+ reply->length = (sizeof *reply - sizeof(xGenericReply) +
+ pFontInfo->nprops * sizeof(xFontProp) +
+ namelen + 3) >> 2;
+ reply->sequenceNumber = client->sequence;
+ reply->nameLength = namelen;
+ reply->minBounds = pFontInfo->ink_minbounds;
+ reply->maxBounds = pFontInfo->ink_maxbounds;
+ reply->minCharOrByte2 = pFontInfo->firstCol;
+ reply->maxCharOrByte2 = pFontInfo->lastCol;
+ reply->defaultChar = pFontInfo->defaultCh;
+ reply->nFontProps = pFontInfo->nprops;
+ reply->drawDirection = pFontInfo->drawDirection;
+ reply->minByte1 = pFontInfo->firstRow;
+ reply->maxByte1 = pFontInfo->lastRow;
+ reply->allCharsExist = pFontInfo->allExist;
+ reply->fontAscent = pFontInfo->fontAscent;
+ reply->fontDescent = pFontInfo->fontDescent;
+ reply->nReplies = numFonts;
+ pFP = (xFontProp *) (reply + 1);
+ for (i = 0; i < pFontInfo->nprops; i++)
+ {
+ pFP->name = pFontInfo->props[i].name;
+ pFP->value = pFontInfo->props[i].value;
+ pFP++;
+ }
+ WriteSwappedDataToClient(client, length, reply);
+ WriteToClient(client, namelen, name);
+ if (pFontInfo == &fontInfo)
+ {
+ free(fontInfo.props);
+ free(fontInfo.isStringProp);
+ }
+ --c->current.max_names;
+ }
+ }
+finish:
+ length = sizeof(xListFontsWithInfoReply);
+ bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
+ finalReply.type = X_Reply;
+ finalReply.sequenceNumber = client->sequence;
+ finalReply.length = (sizeof(xListFontsWithInfoReply)
+ - sizeof(xGenericReply)) >> 2;
+ 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]);
+ free(c->reply);
+ free(c->fpe_list);
+ if (c->savedName) free(c->savedName);
+ free(c);
+ return TRUE;
+}
+
+
+int
+SetDefaultFontPath(char *path)
+{
+ char *temp_path,
+ *start,
+ *end;
+ unsigned char *cp,
+ *pp,
+ *nump,
+ *newpath;
+ int num = 1,
+ len,
+ err,
+ size = 0,
+ bad;
+
+#ifdef NX_TRANS_SOCKET
+ path = (char *) _NXGetFontPath(path);
+#endif /* NX_TRANS_SOCKET */
+
+ start = path;
+
+ /* ensure temp_path contains "built-ins" */
+ while (1) {
+ start = strstr(start, "built-ins");
+ if (start == NULL)
+ break;
+ end = start + strlen("built-ins");
+ if ((start == path || start[-1] == ',') && (!*end || *end == ','))
+ break;
+ start = end;
+ }
+ if (!start) {
+ if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "")
+ == -1)
+ temp_path = NULL;
+ }
+ else {
+ temp_path = strdup(path);
+ }
+ if (!temp_path)
+ return BadAlloc;
+
+ /* get enough for string, plus values -- use up commas */
+ len = strlen(temp_path) + 1;
+ nump = cp = newpath = (unsigned char *) malloc(len);
+ if (!newpath) {
+ free(temp_path);
+ return BadAlloc;
+ }
+ pp = (unsigned char *) temp_path;
+ cp++;
+ while (*pp) {
+ if (*pp == ',') {
+ *nump = (unsigned char) size;
+ nump = cp++;
+ pp++;
+ num++;
+ size = 0;
+ } else {
+ *cp++ = *pp++;
+ size++;
+ }
+ }
+ *nump = (unsigned char) size;
+
+ err = SetFontPathElements(num, newpath, &bad, TRUE);
+
+ free(newpath);
+ free(temp_path);
+
+ return err;
+}
+
+
+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];
+#ifdef HAS_XFONT2
+ (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
+#else
+ (*fpe_functions[fpe->type].client_died) ((void *) client, fpe);
+#endif /* HAS_XFONT2 */
+ }
+ 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;
+
+#ifdef HAS_XFONT2
+ if (!fpe_functions[fpe->type]->start_list_fonts_and_aliases)
+#else
+ if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
+#endif /* HAS_XFONT2 */
+ {
+ /* This FPE doesn't support/require list_fonts_and_aliases */
+
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->list_fonts)
+#else
+ err = (*fpe_functions[fpe->type].list_fonts)
+#endif /* HAS_XFONT2 */
+ ((void *) 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,
+ (void *) 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) {
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->start_list_fonts_and_aliases)
+#else
+ err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
+#endif /* HAS_XFONT2 */
+ ((void *) 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,
+ (void *) 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;
+#ifdef HAS_XFONT2
+ err = (*fpe_functions[fpe->type]->list_next_font_or_alias)
+#else
+ err = (*fpe_functions[fpe->type].list_next_font_or_alias)
+#endif /* HAS_XFONT2 */
+ ((void *) c->client, fpe, &name, &namelen, &tmpname,
+ &resolvedlen, c->current.private);
+ if (err == Suspended) {
+ if (!c->slept) {
+ ClientSleep(client,
+ (ClientSleepProcPtr)nxdoListFontsAndAliases,
+ (void *) 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) free(resolved);
+ resolved = (char *) malloc(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;
+#ifdef HAS_XFONT2
+ (void) (*fpe_functions[fpe->type]->list_next_font_or_alias)
+#else
+ (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
+#endif /* HAS_XFONT2 */
+ ((void *) 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)
+ free(c->savedName);
+ c->savedName = (char *)malloc(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]);
+ free(c->fpe_list);
+ if (c->savedName) free(c->savedName);
+#ifdef HAS_XFONT2
+ xfont2_free_font_names(c->names);
+#else
+ FreeFontNames(c->names);
+#endif /* HAS_XFONT2 */
+ free(c);
+ free(fss);
+ if (resolved) free(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 *)malloc(lenfname + 1);
+ memmove(f, pfontname, lenfname);
+ f[lenfname] = '\0';
+ ErrorF("OpenFont: fontname is \"%s\"\n", f);
+ free(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.
+ */
+
+#ifdef HAS_XFONT2
+ cached = xfont2_find_cached_font_pattern(patternCache, pfontname, lenfname);
+#else
+ cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
+#endif /* HAS_XFONT2 */
+ if (cached && cached->info.cachable)
+ {
+ if (!AddResource(fid, RT_FONT, (void *) cached))
+ return BadAlloc;
+ cached->refcnt++;
+ return Success;
+ }
+ }
+ if (!(fss = (nxFsPtr) malloc(sizeof(nxFs))))
+ return BadAlloc;
+
+ if (!(c = (LFclosurePtr) malloc(sizeof *c)))
+ {
+ free(fss);
+ return BadAlloc;
+ }
+ c->fpe_list = (FontPathElementPtr *)
+ malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ free(c);
+ free(fss);
+ return BadAlloc;
+ }
+#ifdef HAS_XFONT2
+ c->names = xfont2_make_font_names_record(100);
+#else
+ c->names = MakeFontNamesRecord(100);
+#endif /* HAS_XFONT2 */
+ if (!c->names)
+ {
+ free(c->fpe_list);
+ free(c);
+ free(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) malloc(sizeof(OFclosureRec));
+ if (!oc)
+ {
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ free(c->fpe_list);
+ free(c);
+ free(fss);
+ return BadAlloc;
+ }
+ oc->fontname = (char *) malloc(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]);
+ free(c->fpe_list);
+ free(c);
+ free(oc);
+ free(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 *)
+ malloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!oc->fpe_list) {
+ free(oc->fontname);
+ free(oc);
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ free(c->fpe_list);
+ free(c);
+ free(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/nx-X11/programs/Xserver/hw/nxagent/NXevents.c b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c
new file mode 100644
index 000000000..43cb806e7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXevents.c
@@ -0,0 +1,613 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 panoramix components contained the following notice */
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+/*****************************************************************
+
+Copyright 2003-2005 Sun Microsystems, Inc.
+
+All rights reserved.
+
+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, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+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
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+******************************************************************/
+
+
+#include <nx-X11/Xlib.h>
+
+#include "../../dix/events.c"
+
+#include "compext/Compext.h"
+
+#include "Events.h"
+#include "Windows.h"
+#include "Args.h"
+
+extern Display *nxagentDisplay;
+
+extern WindowPtr nxagentLastEnteredWindow;
+
+void
+ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
+ TimeStamp time, Bool autoGrab)
+{
+ WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
+ : sprite.win;
+
+ if (grab->confineTo)
+ {
+ if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
+ sprite.hotPhys.x = sprite.hotPhys.y = 0;
+ ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
+ }
+ DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
+ mouse->valuator->motionHintWindow = NullWindow;
+ if (syncEvents.playingEvents)
+ mouse->grabTime = syncEvents.time;
+ else
+ mouse->grabTime = time;
+ if (grab->cursor)
+ grab->cursor->refcnt++;
+ mouse->activeGrab = *grab;
+ mouse->grab = &mouse->activeGrab;
+ 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
+DeactivatePointerGrab(register DeviceIntPtr mouse)
+{
+ register GrabPtr grab = mouse->grab;
+ register DeviceIntPtr dev;
+
+ mouse->valuator->motionHintWindow = NullWindow;
+ mouse->grab = NullGrab;
+ mouse->sync.state = NOT_GRABBED;
+ mouse->fromPassiveGrab = FALSE;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (dev->sync.other == grab)
+ dev->sync.other = NullGrab;
+ }
+ DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
+ if (grab->confineTo)
+ ConfineCursorToWindow(ROOT, FALSE, FALSE);
+ PostNewCursor();
+ 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
+}
+
+// int
+// ProcAllowEvents(register ClientPtr client)
+// {
+// TimeStamp time;
+// DeviceIntPtr mouse = inputInfo.pointer;
+// DeviceIntPtr keybd = inputInfo.keyboard;
+// REQUEST(xAllowEventsReq);
+//
+// REQUEST_SIZE_MATCH(xAllowEventsReq);
+// time = ClientTimeToServerTime(stuff->time);
+// switch (stuff->mode)
+// {
+// case ReplayPointer:
+// AllowSome(client, time, mouse, NOT_GRABBED);
+// break;
+// case SyncPointer:
+// AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
+// break;
+// case AsyncPointer:
+// AllowSome(client, time, mouse, THAWED);
+// break;
+// case ReplayKeyboard:
+// AllowSome(client, time, keybd, NOT_GRABBED);
+// break;
+// case SyncKeyboard:
+// AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
+// break;
+// case AsyncKeyboard:
+// AllowSome(client, time, keybd, THAWED);
+// break;
+// case SyncBoth:
+// AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
+// break;
+// case AsyncBoth:
+// AllowSome(client, time, keybd, THAWED_BOTH);
+// break;
+// default:
+// 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;
+// }
+
+static WindowPtr
+XYToWindow(int x, int y)
+{
+ register WindowPtr pWin;
+ BoxRec box;
+
+ spriteTraceGood = 1; /* root window still there */
+
+ 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) &&
+ (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+ (x < pWin->drawable.x + (int)pWin->drawable.width +
+ wBorderWidth(pWin)) &&
+ (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+ (y < pWin->drawable.y + (int)pWin->drawable.height +
+ wBorderWidth (pWin))
+#ifdef SHAPE
+ /* When a window is shaped, a further check
+ * is made to see if the point is inside
+ * borderSize
+ */
+ && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+ && (!wInputShape(pWin) ||
+ RegionContainsPoint(
+ wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
+#endif
+ )
+ {
+ if (spriteTraceGood >= spriteTraceSize)
+ {
+ spriteTraceSize += 10;
+ Must_have_memory = TRUE; /* XXX */
+ spriteTrace = (WindowPtr *)realloc(
+ spriteTrace, spriteTraceSize*sizeof(WindowPtr));
+ Must_have_memory = FALSE; /* XXX */
+ }
+ spriteTrace[spriteTraceGood++] = pWin;
+ pWin = pWin->firstChild;
+ }
+ else
+ pWin = pWin->nextSib;
+ }
+ return spriteTrace[spriteTraceGood-1];
+}
+
+// static Bool
+// CheckMotion(xEvent *xE)
+// {
+// WindowPtr prevSpriteWin = sprite.win;
+//
+#ifdef PANORAMIX
+// if(!noPanoramiXExtension)
+// return XineramaCheckMotion(xE);
+#endif
+
+// if (xE && !syncEvents.playingEvents)
+// {
+// if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
+// {
+// sprite.hot.pScreen = sprite.hotPhys.pScreen;
+// ROOT = sprite.hot.pScreen->root;
+// }
+// sprite.hot.x = XE_KBPTR.rootX;
+// sprite.hot.y = XE_KBPTR.rootY;
+// if (sprite.hot.x < sprite.physLimits.x1)
+// sprite.hot.x = sprite.physLimits.x1;
+// else if (sprite.hot.x >= sprite.physLimits.x2)
+// sprite.hot.x = sprite.physLimits.x2 - 1;
+// if (sprite.hot.y < sprite.physLimits.y1)
+// sprite.hot.y = sprite.physLimits.y1;
+// else if (sprite.hot.y >= sprite.physLimits.y2)
+// sprite.hot.y = sprite.physLimits.y2 - 1;
+#ifdef SHAPE
+// if (sprite.hotShape)
+// ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
+#endif
+// sprite.hotPhys = sprite.hot;
+//
+// /*
+// * 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;
+// }
+//
+// sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
+#ifdef notyet
+// if (!(sprite.win->deliverableEvents &
+// Motion_Filter(inputInfo.pointer->button))
+// !syncEvents.playingEvents)
+// {
+// /* XXX Do PointerNonInterestBox here */
+// }
+#endif
+// if (sprite.win != prevSpriteWin)
+// {
+// if (prevSpriteWin != NullWindow) {
+// if (!xE)
+// UpdateCurrentTimeIf();
+// DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
+// }
+// PostNewCursor();
+// return FALSE;
+// }
+// return TRUE;
+// }
+
+void
+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;
+ sprite.hotPhys.y = pScreen->height / 2;
+ sprite.hot = sprite.hotPhys;
+ sprite.hotLimits.x2 = pScreen->width;
+ sprite.hotLimits.y2 = pScreen->height;
+ sprite.win = win;
+ sprite.current = wCursor (win);
+ sprite.current->refcnt++;
+ spriteTraceGood = 1;
+ ROOT = win;
+ (*pScreen->CursorLimits) (
+ pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
+ sprite.confined = FALSE;
+ (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
+ (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
+ (*pScreen->DisplayCursor) (pScreen, sprite.current);
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension) {
+ sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
+ sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
+ sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x;
+ sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
+ sprite.physLimits = sprite.hotLimits;
+ sprite.confineWin = NullWindow;
+#ifdef SHAPE
+ sprite.hotShape = NullRegion;
+#endif
+ sprite.screen = pScreen;
+ /* gotta UNINIT these someplace */
+ RegionNull(&sprite.Reg1);
+ RegionNull(&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);
+ }
+ }
+}
+
+int
+ProcSendEvent(ClientPtr client)
+{
+ WindowPtr pWin;
+ WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
+ REQUEST(xSendEventReq);
+
+ REQUEST_SIZE_MATCH(xSendEventReq);
+
+ /* 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 &&
+ stuff->event.u.u.type < (unsigned)lastEvent)))
+ {
+ client->errorValue = stuff->event.u.u.type;
+ return BadValue;
+ }
+ if (stuff->event.u.u.type == ClientMessage &&
+ stuff->event.u.u.detail != 8 &&
+ stuff->event.u.u.detail != 16 &&
+ stuff->event.u.u.detail != 32 &&
+ !permitOldBugs)
+ {
+ client->errorValue = stuff->event.u.u.detail;
+ return BadValue;
+ }
+ if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+
+ if (stuff->destination == PointerWindow)
+ pWin = sprite.win;
+ else if (stuff->destination == InputFocus)
+ {
+ WindowPtr inputFocus = inputInfo.keyboard->focus->win;
+
+ if (inputFocus == NoneWin)
+ return Success;
+
+ /* If the input focus is PointerRootWin, send the event to where
+ the pointer is if possible, then perhaps propogate up to root. */
+ if (inputFocus == PointerRootWin)
+ inputFocus = ROOT;
+
+ if (IsParent(inputFocus, sprite.win))
+ {
+ effectiveFocus = inputFocus;
+ pWin = sprite.win;
+ }
+ else
+ effectiveFocus = pWin = inputFocus;
+ }
+ else
+ pWin = SecurityLookupWindow(stuff->destination, client,
+ DixReadAccess);
+ if (!pWin)
+ return BadWindow;
+ if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
+ {
+ client->errorValue = stuff->propagate;
+ return BadValue;
+ }
+ stuff->event.u.u.type |= 0x80;
+ if (stuff->propagate)
+ {
+ for (;pWin; pWin = pWin->parent)
+ {
+ if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
+ NullGrab, 0))
+ return Success;
+ if (pWin == effectiveFocus)
+ return Success;
+ stuff->eventMask &= ~wDontPropagateMask(pWin);
+ if (!stuff->eventMask)
+ break;
+ }
+ }
+ else
+ (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
+ NullGrab, 0);
+ return Success;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXextension.c b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c
new file mode 100644
index 000000000..9ec6be8ef
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXextension.c
@@ -0,0 +1,195 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+
+#include "Trap.h"
+
+#include "../../dix/extension.c"
+
+int
+ProcQueryExtension(ClientPtr client)
+{
+ xQueryExtensionReply reply;
+ int i;
+ REQUEST(xQueryExtensionReq);
+
+ REQUEST_FIXED_SIZE(xQueryExtensionReq, stuff->nbytes);
+
+ memset(&reply, 0, sizeof(xQueryExtensionReply));
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.major_opcode = 0;
+ reply.sequenceNumber = client->sequence;
+
+ if ( ! NumExtensions )
+ reply.present = xFalse;
+ else
+ {
+ 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 &&
+ !extensions[i]->secure)
+#endif
+ )
+ reply.present = xFalse;
+ else
+ {
+ reply.present = xTrue;
+ reply.major_opcode = extensions[i]->base;
+ reply.first_event = extensions[i]->eventBase;
+ reply.first_error = extensions[i]->errorBase;
+ }
+ }
+ WriteReplyToClient(client, sizeof(xQueryExtensionReply), &reply);
+ return(client->noClientException);
+}
+
+int
+ProcListExtensions(ClientPtr client)
+{
+ xListExtensionsReply reply;
+ char *bufptr, *buffer;
+ int total_length = 0;
+
+ REQUEST_SIZE_MATCH(xReq);
+
+ memset(&reply, 0, sizeof(xListExtensionsReply));
+ reply.type = X_Reply;
+ reply.nExtensions = 0;
+ reply.length = 0;
+ reply.sequenceNumber = client->sequence;
+ buffer = NULL;
+
+ if ( NumExtensions )
+ {
+ register int i, j;
+
+ for (i=0; i<NumExtensions; i++)
+ {
+#ifdef XCSECURITY
+ /* don't show insecure extensions to untrusted clients */
+ if (client->trustLevel == XSecurityClientUntrusted &&
+ !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;)
+ total_length += strlen(extensions[i]->aliases[j]) + 1;
+ }
+ reply.length = (total_length + 3) >> 2;
+ buffer = bufptr = (char *)malloc(total_length);
+ if (!buffer)
+ return(BadAlloc);
+ for (i=0; i<NumExtensions; i++)
+ {
+ int len;
+#ifdef XCSECURITY
+ if (client->trustLevel == XSecurityClientUntrusted &&
+ !extensions[i]->secure)
+ continue;
+#endif
+ *bufptr++ = len = strlen(extensions[i]->name);
+ memmove(bufptr, extensions[i]->name, len);
+ bufptr += len;
+ for (j = extensions[i]->num_aliases; --j >= 0;)
+ {
+ *bufptr++ = len = strlen(extensions[i]->aliases[j]);
+ memmove(bufptr, extensions[i]->aliases[j], len);
+ bufptr += len;
+ }
+ }
+ }
+ WriteReplyToClient(client, sizeof(xListExtensionsReply), &reply);
+ if (reply.length)
+ {
+ WriteToClient(client, total_length, buffer);
+ free(buffer);
+ }
+ return(client->noClientException);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c
new file mode 100644
index 000000000..5512cae1b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXglxext.c
@@ -0,0 +1,204 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+** 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
+** License. You may obtain a copy of the License at Silicon Graphics, Inc.,
+** attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043
+** or at http://www.sgi.com/software/opensource/glx/license.html.
+**
+** Software distributed under the License is distributed on an "AS IS"
+** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY
+** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
+** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific
+** language governing rights and limitations under the License.
+**
+** The Original Software is GLX version 1.2 source code, released February,
+** 1999. The developer of the Original Software is Silicon Graphics, Inc.
+** Those portions of the Subject Software created by Silicon Graphics, Inc.
+** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
+**
+*/
+
+#include "../../GL/glx/glxext.c"
+
+#include "Trap.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+** Top level dispatcher; all commands are executed from here down.
+*/
+static int __glXDispatch(ClientPtr client)
+{
+ int result;
+
+ REQUEST(xGLXSingleReq);
+ CARD8 opcode;
+ int (*proc)(__GLXclientState *cl, GLbyte *pc);
+ __GLXclientState *cl;
+
+ opcode = stuff->glxCode;
+ cl = __glXClients[client->index];
+ if (!cl) {
+ cl = (__GLXclientState *) malloc(sizeof(__GLXclientState));
+ __glXClients[client->index] = cl;
+ if (!cl) {
+ return BadAlloc;
+ }
+ memset(cl, 0, sizeof(__GLXclientState));
+ }
+
+ if (!cl->inUse) {
+ /*
+ ** This is first request from this client. Associate a resource
+ ** with the client so we will be notified when the client dies.
+ */
+ XID xid = FakeClientID(client->index);
+ if (!AddResource( xid, __glXClientRes, (void *)(long)client->index)) {
+ return BadAlloc;
+ }
+ ResetClientState(client->index);
+ cl->inUse = GL_TRUE;
+ cl->client = client;
+ }
+
+ /*
+ ** Check for valid opcode.
+ */
+ if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
+ return BadRequest;
+ }
+
+ /*
+ ** If we're expecting a glXRenderLarge request, this better be one.
+ */
+ if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
+ client->errorValue = stuff->glxCode;
+ return __glXBadLargeRequest;
+ }
+
+ /*
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXSingleTable[opcode];
+
+ /*
+ * 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);
+ __GLXclientState *cl;
+
+ opcode = stuff->glxCode;
+ cl = __glXClients[client->index];
+ if (!cl) {
+ cl = (__GLXclientState *) malloc(sizeof(__GLXclientState));
+ __glXClients[client->index] = cl;
+ if (!cl) {
+ return BadAlloc;
+ }
+ memset(cl, 0, sizeof(__GLXclientState));
+ }
+
+ if (!cl->inUse) {
+ /*
+ ** This is first request from this client. Associate a resource
+ ** with the client so we will be notified when the client dies.
+ */
+ XID xid = FakeClientID(client->index);
+ if (!AddResource( xid, __glXClientRes, (void *)(long)client->index)) {
+ return BadAlloc;
+ }
+ ResetClientState(client->index);
+ cl->inUse = GL_TRUE;
+ cl->client = client;
+ }
+
+ /*
+ ** Check for valid opcode.
+ */
+ if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
+ return BadRequest;
+ }
+
+ /*
+ ** Use the opcode to index into the procedure table.
+ */
+ proc = __glXSwapSingleTable[opcode];
+
+ /*
+ * 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;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c
new file mode 100644
index 000000000..35dcbc132
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyph.c
@@ -0,0 +1,381 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+#include "../../render/glyph.c"
+
+#ifdef NXAGENT_SERVER
+
+#include "Render.h"
+
+#define PANIC
+#define WARNING
+#undef DEBUG
+#undef TEST
+
+#endif
+
+void
+AddGlyph (GlyphSetPtr glyphSet, GlyphPtr glyph, Glyph id)
+{
+ GlyphRefPtr gr;
+ CARD32 hash;
+
+ CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph top global");
+ /* Locate existing matching glyph */
+ hash = HashGlyph (glyph);
+ gr = FindGlyphRef (&globalGlyphs[glyphSet->fdepth], hash, TRUE, glyph);
+ if (gr->glyph && gr->glyph != DeletedGlyph)
+ {
+ free (glyph);
+ glyph = gr->glyph;
+ }
+ else
+ {
+ gr->glyph = glyph;
+ gr->signature = hash;
+ globalGlyphs[glyphSet->fdepth].tableEntries++;
+ }
+
+ /* Insert/replace glyphset value */
+ gr = FindGlyphRef (&glyphSet->hash, id, FALSE, 0);
+ ++glyph->refcnt;
+ if (gr->glyph && gr->glyph != DeletedGlyph)
+ FreeGlyph (gr->glyph, glyphSet->fdepth);
+ else
+ glyphSet->hash.tableEntries++;
+ gr->glyph = glyph;
+ gr->signature = id;
+
+ #ifdef NXAGENT_SERVER
+
+ gr -> corruptedGlyph = 1;
+
+ #endif
+
+ CheckDuplicates (&globalGlyphs[glyphSet->fdepth], "AddGlyph bottom");
+}
+
+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;
+}
+
+Bool
+ResizeGlyphHash (GlyphHashPtr hash, CARD32 change, Bool global)
+{
+ CARD32 tableEntries;
+ GlyphHashSetPtr hashSet;
+ GlyphHashRec newHash;
+ GlyphRefPtr gr;
+ GlyphPtr glyph;
+ int i;
+ int oldSize;
+ CARD32 s;
+
+ #ifdef NXAGENT_SERVER
+
+ CARD32 c;
+
+ #endif
+
+ tableEntries = hash->tableEntries + change;
+ hashSet = FindGlyphHashSet (tableEntries);
+ if (hashSet == hash->hashSet)
+ return TRUE;
+ if (global)
+ CheckDuplicates (hash, "ResizeGlyphHash top");
+ if (!AllocateGlyphHash (&newHash, hashSet))
+ return FALSE;
+ if (hash->table)
+ {
+ oldSize = hash->hashSet->size;
+ for (i = 0; i < oldSize; i++)
+ {
+ glyph = hash->table[i].glyph;
+ 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;
+ }
+ }
+ free (hash->table);
+ }
+ *hash = newHash;
+ if (global)
+ CheckDuplicates (hash, "ResizeGlyphHash bottom");
+ return TRUE;
+}
+
+void
+miGlyphs (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlist,
+ GlyphListPtr list,
+ GlyphPtr *glyphs)
+{
+ PixmapPtr pPixmap = 0;
+ PicturePtr pPicture;
+ PixmapPtr pMaskPixmap = 0;
+ PicturePtr pMask;
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ int width = 0, height = 0;
+ int x, y;
+ int xDst = list->xOff, yDst = list->yOff;
+ int n;
+ GlyphPtr glyph;
+ int error;
+ BoxRec extents;
+ CARD32 component_alpha;
+
+ /*
+ * Get rid of the warning.
+ */
+
+ extents.x1 = 0;
+ extents.y1 = 0;
+
+ if (maskFormat)
+ {
+ GCPtr pGC;
+ xRectangle rect;
+
+ if (nxagentGlyphsExtents != NullBox)
+ {
+ memcpy(&extents, nxagentGlyphsExtents, sizeof(BoxRec));
+ }
+ else
+ {
+ nxagentGlyphsExtents = (BoxPtr) malloc(sizeof(BoxRec));
+
+ GlyphExtents (nlist, list, glyphs, &extents);
+
+ memcpy(nxagentGlyphsExtents, &extents, sizeof(BoxRec));
+ }
+
+ 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,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+
+ if (!pMaskPixmap)
+ return;
+
+ component_alpha = NeedsComponent(maskFormat->format);
+ pMask = CreatePicture (0, &pMaskPixmap->drawable,
+ maskFormat, CPComponentAlpha, &component_alpha,
+ serverClient, &error);
+
+ if (!pMask)
+ {
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ return;
+ }
+ pGC = GetScratchGC (pMaskPixmap->drawable.depth, pScreen);
+ ValidateGC (&pMaskPixmap->drawable, pGC);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
+ FreeScratchGC (pGC);
+ x = -extents.x1;
+ y = -extents.y1;
+ }
+ else
+ {
+ pMask = pDst;
+ x = 0;
+ y = 0;
+ }
+ pPicture = 0;
+ while (nlist--)
+ {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+
+ while (n--)
+ {
+ glyph = *glyphs++;
+ if (!pPicture)
+ {
+ pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height,
+ list->format->depth,
+ list->format->depth,
+ 0, (void *) (glyph + 1));
+ if (!pPixmap)
+ return;
+ component_alpha = NeedsComponent(list->format->format);
+ pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
+ CPComponentAlpha, &component_alpha,
+ serverClient, &error);
+ if (!pPicture)
+ {
+ FreeScratchPixmapHeader (pPixmap);
+ return;
+ }
+ }
+ (*pScreen->ModifyPixmapHeader) (pPixmap,
+ glyph->info.width, glyph->info.height,
+ 0, 0, -1, (void *) (glyph + 1));
+
+ /*
+ * 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;
+
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ if (maskFormat)
+ {
+ CompositePicture (PictOpAdd,
+ pPicture,
+ None,
+ pMask,
+ 0, 0,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
+ else
+ {
+ CompositePicture (op,
+ pSrc,
+ pPicture,
+ pDst,
+ xSrc + (x - glyph->info.x) - xDst,
+ ySrc + (y - glyph->info.y) - yDst,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+
+ list++;
+ if (pPicture)
+ {
+ FreeScratchPixmapHeader (pPixmap);
+ FreePicture ((void *) pPicture, 0);
+ pPicture = 0;
+ pPixmap = 0;
+ }
+ }
+ if (maskFormat)
+ {
+ x = extents.x1;
+ y = extents.y1;
+ CompositePicture (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc + x - xDst,
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+
+ FreePicture ((void *) pMask, (XID) 0);
+ (*pScreen->DestroyPixmap) (pMaskPixmap);
+ }
+
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c
new file mode 100644
index 000000000..549ab4333
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphcurs.c
@@ -0,0 +1,180 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+************************************************************************/
+
+
+#include "../../dix/glyphcurs.c"
+
+#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
+dealing with padding and such-like, we draw the glyph into
+a bitmap, then read the bits out with GetImage, which
+uses server-natural format.
+ since all screens return the same bitmap format, we'll just use
+the first one we find.
+ the character origin lines up with the hotspot in the
+cursor metrics.
+*/
+
+int
+ServerBitsFromGlyph(FontPtr pfont, unsigned ch, register CursorMetricPtr cm, unsigned char **ppbits)
+{
+ register ScreenPtr pScreen;
+ register GCPtr pGC;
+ xRectangle rect;
+ PixmapPtr ppix;
+ long nby;
+ char *pbits;
+ unsigned char char2b[2];
+
+ /* turn glyph index into a protocol-format char2b */
+ char2b[0] = (unsigned char)(ch >> 8);
+ char2b[1] = (unsigned char)(ch & 0xff);
+
+ pScreen = screenInfo.screens[0];
+ nby = BitmapBytePad(cm->width) * (long)cm->height;
+ pbits = (char *)malloc(nby);
+ if (!pbits)
+ return BadAlloc;
+ /* zeroing the (pad) bits seems to help some ddx cursor handling */
+ bzero(pbits, nby);
+
+ ppix = fbCreatePixmap(pScreen, cm->width, cm->height, 1,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ pGC = GetScratchGC(1, pScreen);
+ if (!ppix || !pGC)
+ {
+ if (ppix)
+ fbDestroyPixmap(ppix);
+ if (pGC)
+ FreeScratchGC(pGC);
+ free(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;
+
+ 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);
+ fbPolyFillRect((DrawablePtr)ppix, pGC, 1, &rect);
+
+ /* draw the glyph */
+ pGC->fgPixel = 1;
+
+ pGC->stateChanges |= GCForeground;
+
+ ValidateGC((DrawablePtr)ppix, pGC);
+ 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);
+ fbDestroyPixmap(ppix);
+
+ #ifdef TEST
+ fprintf(stderr, "ServerBitsFromGlyph: Destroyed virtual pixmap at [%p].\n",
+ (void *) ppix);
+ #endif
+
+ return Success;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphRef.h b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphRef.h
new file mode 100644
index 000000000..eef2da8dd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphRef.h
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+/* this header file gets included into Xserver/render/glyphstr.h */
+
+#ifndef NX_GLYPHSTR_GLYPHREF_H
+#define NX_GLYPHSTR_GLYPHREF_H 1
+
+typedef struct _GlyphRef {
+ CARD32 signature;
+ GlyphPtr glyph;
+ CARD16 corruptedGlyph;
+} GlyphRefRec, *GlyphRefPtr;
+
+#endif /* NX_GLYPHSTR_GLYPHREF_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphSet.h b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphSet.h
new file mode 100644
index 000000000..98f331dd7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXglyphstr_GlyphSet.h
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+/* this header file gets included into Xserver/render/glyphstr.h */
+
+#ifndef NX_GLYPHSTR_GLYPHSET_H
+#define NX_GLYPHSTR_GLYPHSET_H 1
+
+typedef struct _GlyphSet {
+ CARD32 refcnt;
+ PictFormatPtr format;
+ int fdepth;
+ GlyphHashRec hash;
+ int maxPrivate;
+ void **devPrivates;
+ CARD32 remoteID;
+} GlyphSetRec, *GlyphSetPtr;
+
+#endif /* NX_GLYPHSTR_GLYPHSET_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c
new file mode 100644
index 000000000..bcb88d42d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXmiexpose.c
@@ -0,0 +1,743 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+
+#include "Windows.h"
+
+#include "../../mi/miexpose.c"
+
+/* miHandleExposures
+ generate a region for exposures for areas that were copied from obscured or
+non-existent areas to non-obscured areas of the destination. Paint the
+background for the region, if the destination is a window.
+
+NOTE:
+ this should generally be called, even if graphicsExposures is false,
+because this is where bits get recovered from backing store.
+
+NOTE:
+ added argument 'plane' is used to indicate how exposures from backing
+store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
+should be used, else a CopyPlane of the indicated plane will be used. The
+exposing is done by the backing store's GraphicsExpose function, of course.
+
+*/
+
+RegionPtr
+miHandleExposures(pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy, width, height, dstx, dsty, plane)
+ register DrawablePtr pSrcDrawable;
+ register DrawablePtr pDstDrawable;
+ GCPtr pGC;
+ int srcx, srcy;
+ int width, height;
+ int dstx, dsty;
+ unsigned long plane;
+{
+ register ScreenPtr pscr;
+ RegionPtr prgnSrcClip; /* drawable-relative source clip */
+ RegionRec rgnSrcRec;
+ RegionPtr prgnDstClip; /* drawable-relative dest clip */
+ RegionRec rgnDstRec;
+ BoxRec srcBox; /* unclipped source */
+ RegionRec rgnExposed; /* exposed region, calculated source-
+ relative, made dst relative to
+ intersect with visible parts of
+ dest and send events to client,
+ and then screen relative to paint
+ the window background
+ */
+ WindowPtr pSrcWin;
+ BoxRec expBox;
+ Bool extents;
+
+ /*
+ * Set the elements reported by the compiler
+ * as uninitialized.
+ */
+
+ expBox.x1 = 0;
+ expBox.y1 = 0;
+ expBox.x2 = 0;
+ expBox.y2 = 0;
+
+ /* This prevents warning about pscr not being used. */
+ pGC->pScreen = pscr = pGC->pScreen;
+
+ /* avoid work if we can */
+ if (!pGC->graphicsExposures &&
+ (pDstDrawable->type == DRAWABLE_PIXMAP) &&
+ ((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
+ (((WindowPtr)pSrcDrawable)->backStorage == NULL)))
+ return NULL;
+
+ srcBox.x1 = srcx;
+ srcBox.y1 = srcy;
+ srcBox.x2 = srcx+width;
+ srcBox.y2 = srcy+height;
+
+ if (pSrcDrawable->type != DRAWABLE_PIXMAP)
+ {
+ BoxRec TsrcBox;
+
+ TsrcBox.x1 = srcx + pSrcDrawable->x;
+ TsrcBox.y1 = srcy + pSrcDrawable->y;
+ TsrcBox.x2 = TsrcBox.x1 + width;
+ TsrcBox.y2 = TsrcBox.y1 + height;
+ pSrcWin = (WindowPtr) pSrcDrawable;
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ prgnSrcClip = NotClippedByChildren (pSrcWin);
+ if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN)
+ {
+ RegionDestroy(prgnSrcClip);
+ return NULL;
+ }
+ }
+ else
+ {
+ if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
+ return NULL;
+ prgnSrcClip = &rgnSrcRec;
+ RegionNull(prgnSrcClip);
+ RegionCopy(prgnSrcClip, &pSrcWin->clipList);
+ }
+ RegionTranslate(prgnSrcClip,
+ -pSrcDrawable->x, -pSrcDrawable->y);
+ }
+ else
+ {
+ BoxRec box;
+
+ if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
+ (srcBox.x2 <= pSrcDrawable->width) &&
+ (srcBox.y2 <= pSrcDrawable->height))
+ return NULL;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pSrcDrawable->width;
+ box.y2 = pSrcDrawable->height;
+ prgnSrcClip = &rgnSrcRec;
+ RegionInit(prgnSrcClip, &box, 1);
+ pSrcWin = (WindowPtr)NULL;
+ }
+
+ if (pDstDrawable == pSrcDrawable)
+ {
+ prgnDstClip = prgnSrcClip;
+ }
+ else if (pDstDrawable->type != DRAWABLE_PIXMAP)
+ {
+ if (pGC->subWindowMode == IncludeInferiors)
+ {
+ prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
+ }
+ else
+ {
+ prgnDstClip = &rgnDstRec;
+ RegionNull(prgnDstClip);
+ RegionCopy(prgnDstClip,
+ &((WindowPtr)pDstDrawable)->clipList);
+ }
+ RegionTranslate(prgnDstClip,
+ -pDstDrawable->x, -pDstDrawable->y);
+ }
+ else
+ {
+ BoxRec box;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pDstDrawable->width;
+ box.y2 = pDstDrawable->height;
+ prgnDstClip = &rgnDstRec;
+ RegionInit(prgnDstClip, &box, 1);
+ }
+
+ /* drawable-relative source region */
+ RegionInit(&rgnExposed, &srcBox, 1);
+
+ /* now get the hidden parts of the source box*/
+ RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
+
+ if (pSrcWin && pSrcWin->backStorage)
+ {
+ /*
+ * Copy any areas from the source backing store. Modifies
+ * rgnExposed.
+ */
+ (* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable,
+ pDstDrawable,
+ pGC,
+ &rgnExposed,
+ srcx, srcy,
+ dstx, dsty,
+ plane);
+ }
+
+ /* move them over the destination */
+ RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy);
+
+ /* intersect with visible areas of dest */
+ RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
+
+ /*
+ * If we have LOTS of rectangles, we decide to take the extents
+ * and force an exposure on that. This should require much less
+ * work overall, on both client and server. This is cheating, but
+ * isn't prohibited by the protocol ("spontaneous combustion" :-)
+ * for windows.
+ */
+ extents = pGC->graphicsExposures &&
+ (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
+ (pDstDrawable->type != DRAWABLE_PIXMAP);
+#ifdef SHAPE
+ if (pSrcWin)
+ {
+ RegionPtr region;
+ if (!(region = wClipShape (pSrcWin)))
+ region = wBoundingShape (pSrcWin);
+ /*
+ * If you try to CopyArea the extents of a shaped window, compacting the
+ * exposed region will undo all our work!
+ */
+ if (extents && pSrcWin && region &&
+ (RegionContainsRect(region, &srcBox) != rgnIN))
+ extents = FALSE;
+ }
+#endif
+ if (extents)
+ {
+ WindowPtr pWin = (WindowPtr)pDstDrawable;
+
+ expBox = *RegionExtents(&rgnExposed);
+ RegionReset(&rgnExposed, &expBox);
+ /* need to clear out new areas of backing store */
+ if (pWin->backStorage)
+ (void) (* pWin->drawable.pScreen->ClearBackingStore)(
+ pWin,
+ expBox.x1,
+ expBox.y1,
+ expBox.x2 - expBox.x1,
+ expBox.y2 - expBox.y1,
+ FALSE);
+ }
+ if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
+ (((WindowPtr)pDstDrawable)->backgroundState != None))
+ {
+ WindowPtr pWin = (WindowPtr)pDstDrawable;
+
+ /* make the exposed area screen-relative */
+ RegionTranslate(&rgnExposed,
+ pDstDrawable->x, pDstDrawable->y);
+
+ if (extents)
+ {
+ /* PaintWindowBackground doesn't clip, so we have to */
+ RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
+ }
+ (*pWin->drawable.pScreen->PaintWindowBackground)(
+ (WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
+
+ if (extents)
+ {
+ RegionReset(&rgnExposed, &expBox);
+ }
+ else
+ RegionTranslate(&rgnExposed,
+ -pDstDrawable->x, -pDstDrawable->y);
+ }
+ if (prgnDstClip == &rgnDstRec)
+ {
+ RegionUninit(prgnDstClip);
+ }
+ else if (prgnDstClip != prgnSrcClip)
+ {
+ RegionDestroy(prgnDstClip);
+ }
+
+ if (prgnSrcClip == &rgnSrcRec)
+ {
+ RegionUninit(prgnSrcClip);
+ }
+ else
+ {
+ RegionDestroy(prgnSrcClip);
+ }
+
+ if (pGC->graphicsExposures)
+ {
+ /* don't look */
+ RegionPtr exposed = RegionCreate(NullBox, 0);
+ *exposed = rgnExposed;
+ return exposed;
+ }
+ else
+ {
+ RegionUninit(&rgnExposed);
+ return NULL;
+ }
+}
+
+void
+miWindowExposures(pWin, prgn, other_exposed)
+ WindowPtr pWin;
+ register RegionPtr prgn, other_exposed;
+{
+
+ int total;
+
+ RegionPtr exposures = prgn;
+ if (pWin->backStorage && prgn)
+ /*
+ * in some cases, backing store will cause a different
+ * region to be exposed than needs to be repainted
+ * (like when a window is mapped). RestoreAreas is
+ * allowed to return a region other than prgn,
+ * in which case this routine will free the resultant
+ * region. If exposures is null, then no events will
+ * be sent to the client; if prgn is empty
+ * no areas will be repainted.
+ */
+ exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
+ if ((prgn && !RegionNil(prgn)) ||
+ (exposures && !RegionNil(exposures)) || other_exposed)
+ {
+ RegionRec expRec;
+ int clientInterested;
+
+ /*
+ * Restore from backing-store FIRST.
+ */
+ clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
+ if (other_exposed)
+ {
+ if (exposures)
+ {
+ RegionUnion(other_exposed,
+ exposures,
+ other_exposed);
+ if (exposures != prgn)
+ RegionDestroy(exposures);
+ }
+ exposures = other_exposed;
+ }
+
+ /*
+ * If the number of rectangles is greater
+ * than 4, let the function decide.
+ */
+
+ total = RegionNumRects(exposures);
+
+ if (clientInterested && exposures && (total > RECTLIMIT ||
+ (total > 4 && nxagentExtentsPredicate(total) == 1)))
+ {
+ /*
+ * If we have LOTS of rectangles, we decide to take the extents
+ * and force an exposure on that. This should require much less
+ * work overall, on both client and server. This is cheating, but
+ * isn't prohibited by the protocol ("spontaneous combustion" :-).
+ */
+ BoxRec box;
+
+ box = *RegionExtents(exposures);
+ if (exposures == prgn) {
+ exposures = &expRec;
+ RegionInit(exposures, &box, 1);
+ RegionReset(prgn, &box);
+ } else {
+ RegionReset(exposures, &box);
+ RegionUnion(prgn, prgn, exposures);
+ }
+ /* PaintWindowBackground doesn't clip, so we have to */
+ RegionIntersect(prgn, prgn, &pWin->clipList);
+ /* need to clear out new areas of backing store, too */
+ if (pWin->backStorage)
+ (void) (* pWin->drawable.pScreen->ClearBackingStore)(
+ pWin,
+ box.x1 - pWin->drawable.x,
+ box.y1 - pWin->drawable.y,
+ box.x2 - box.x1,
+ box.y2 - box.y1,
+ FALSE);
+ }
+ if (prgn && !RegionNil(prgn))
+ (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
+ if (clientInterested && exposures && !RegionNil(exposures))
+ miSendExposures(pWin, exposures,
+ pWin->drawable.x, pWin->drawable.y);
+ if (exposures == &expRec)
+ {
+ RegionUninit(exposures);
+ }
+ else if (exposures && exposures != prgn && exposures != other_exposed)
+ RegionDestroy(exposures);
+ if (prgn)
+ RegionEmpty(prgn);
+ }
+ else if (exposures && exposures != prgn)
+ RegionDestroy(exposures);
+}
+
+void
+miPaintWindow(pWin, prgn, what)
+register WindowPtr pWin;
+RegionPtr prgn;
+int what;
+{
+ int status;
+
+ Bool usingScratchGC = FALSE;
+ WindowPtr pRoot;
+
+#define FUNCTION 0
+#define FOREGROUND 1
+#define TILE 2
+#define FILLSTYLE 3
+#define ABSX 4
+#define ABSY 5
+#define CLIPMASK 6
+#define SUBWINDOW 7
+#define COUNT_BITS 8
+
+ ChangeGCVal gcval[7];
+ ChangeGCVal newValues [COUNT_BITS] = {{ 0 }};
+
+ BITS32 gcmask, index, mask;
+ RegionRec prgnWin;
+ DDXPointRec oldCorner;
+ BoxRec box;
+ WindowPtr pBgWin;
+ GCPtr pGC;
+ register int i;
+ register BoxPtr pbox;
+ register ScreenPtr pScreen = pWin->drawable.pScreen;
+ register xRectangle *prect;
+ int numRects;
+
+ /*
+ * 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;
+
+ gcmask = 0;
+
+ if (what == PW_BACKGROUND)
+ {
+ switch (pWin->backgroundState) {
+ case None:
+ return;
+ case ParentRelative:
+ (*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what);
+ return;
+ case BackgroundPixel:
+ newValues[FOREGROUND].val = pWin->background.pixel;
+ newValues[FILLSTYLE].val = FillSolid;
+ gcmask |= GCForeground | GCFillStyle;
+ break;
+ case BackgroundPixmap:
+ newValues[TILE].ptr = (void *)pWin->background.pixmap;
+ newValues[FILLSTYLE].val = FillTiled;
+ gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
+ break;
+ }
+ }
+ else
+ {
+ if (pWin->borderIsPixel)
+ {
+ newValues[FOREGROUND].val = pWin->border.pixel;
+ newValues[FILLSTYLE].val = FillSolid;
+ gcmask |= GCForeground | GCFillStyle;
+ }
+ else
+ {
+ newValues[TILE].ptr = (void *)pWin->border.pixmap;
+ newValues[FILLSTYLE].val = FillTiled;
+ gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
+ }
+ }
+
+ prect = (xRectangle *)malloc(RegionNumRects(prgn) *
+ sizeof(xRectangle));
+ if (!prect)
+ return;
+
+ newValues[FUNCTION].val = GXcopy;
+ gcmask |= GCFunction | GCClipMask;
+
+ i = pScreen->myNum;
+ pRoot = screenInfo.screens[i]->root;
+
+ pBgWin = pWin;
+ if (what == PW_BORDER)
+ {
+ while (pBgWin->backgroundState == ParentRelative)
+ pBgWin = pBgWin->parent;
+ }
+
+ if ((pWin->drawable.depth != pRoot->drawable.depth) ||
+ (pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel))
+ {
+ usingScratchGC = TRUE;
+ pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
+ if (!pGC)
+ {
+ free(prect);
+ return;
+ }
+ /*
+ * mash the clip list so we can paint the border by
+ * mangling the window in place, pretending it
+ * spans the entire screen
+ */
+ if (what == PW_BORDER)
+ {
+ prgnWin = pWin->clipList;
+ oldCorner.x = pWin->drawable.x;
+ oldCorner.y = pWin->drawable.y;
+ pWin->drawable.x = pWin->drawable.y = 0;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ RegionInit(&pWin->clipList, &box, 1);
+ pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ newValues[ABSX].val = pBgWin->drawable.x;
+ newValues[ABSY].val = pBgWin->drawable.y;
+ }
+ else
+ {
+ newValues[ABSX].val = 0;
+ newValues[ABSY].val = 0;
+ }
+ } else {
+ /*
+ * draw the background to the root window
+ */
+ if (screenContext[i] == (GCPtr)NULL)
+ {
+ if (!ResType && !(ResType = CreateNewResourceType(tossGC)))
+ return;
+ screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0,
+ (XID *)NULL, &status);
+ if (!screenContext[i])
+ return;
+ numGCs++;
+ if (!AddResource(FakeClientID(0), ResType,
+ (void *)screenContext[i]))
+ return;
+ }
+ pGC = screenContext[i];
+ newValues[SUBWINDOW].val = IncludeInferiors;
+ newValues[ABSX].val = pBgWin->drawable.x;
+ newValues[ABSY].val = pBgWin->drawable.y;
+ gcmask |= GCSubwindowMode;
+ pWin = pRoot;
+ }
+
+ if (pWin->backStorage)
+ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
+
+ mask = gcmask;
+ gcmask = 0;
+ i = 0;
+ while (mask) {
+ index = lowbit (mask);
+ mask &= ~index;
+ switch (index) {
+ case GCFunction:
+ if (pGC->alu != newValues[FUNCTION].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[FUNCTION].val;
+ }
+ break;
+ case GCTileStipXOrigin:
+ if ( pGC->patOrg.x != newValues[ABSX].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[ABSX].val;
+ }
+ break;
+ case GCTileStipYOrigin:
+ if ( pGC->patOrg.y != newValues[ABSY].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[ABSY].val;
+ }
+ break;
+ case GCClipMask:
+ if ( pGC->clientClipType != CT_NONE) {
+ gcmask |= index;
+ gcval[i++].val = CT_NONE;
+ }
+ break;
+ case GCSubwindowMode:
+ if ( pGC->subWindowMode != newValues[SUBWINDOW].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[SUBWINDOW].val;
+ }
+ break;
+ case GCTile:
+ if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr)
+ {
+ gcmask |= index;
+ gcval[i++].ptr = newValues[TILE].ptr;
+ }
+ break;
+ case GCFillStyle:
+ if ( pGC->fillStyle != newValues[FILLSTYLE].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[FILLSTYLE].val;
+ }
+ break;
+ case GCForeground:
+ if ( pGC->fgPixel != newValues[FOREGROUND].val) {
+ gcmask |= index;
+ gcval[i++].val = newValues[FOREGROUND].val;
+ }
+ break;
+ }
+ }
+
+ if (gcmask)
+ dixChangeGC(NullClient, pGC, gcmask, NULL, gcval);
+
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC((DrawablePtr)pWin, pGC);
+
+ numRects = RegionNumRects(prgn);
+ pbox = RegionRects(prgn);
+ for (i= numRects; --i >= 0; pbox++, prect++)
+ {
+ prect->x = pbox->x1 - pWin->drawable.x;
+ prect->y = pbox->y1 - pWin->drawable.y;
+ prect->width = pbox->x2 - pbox->x1;
+ prect->height = pbox->y2 - pbox->y1;
+ }
+ prect -= numRects;
+ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
+ free(prect);
+
+ if (pWin->backStorage)
+ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
+
+ if (usingScratchGC)
+ {
+ if (what == PW_BORDER)
+ {
+ RegionUninit(&pWin->clipList);
+ pWin->clipList = prgnWin;
+ pWin->drawable.x = oldCorner.x;
+ pWin->drawable.y = oldCorner.y;
+ pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ }
+ FreeScratchGC(pGC);
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c
new file mode 100644
index 000000000..1988ca102
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXmitrap.c
@@ -0,0 +1,123 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#include "Render.h"
+
+#include "../../render/mitrap.c"
+
+void
+miTrapezoids (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntrap,
+ xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ /*
+ * Check for solid alpha add
+ */
+ if (op == PictOpAdd && miIsSolidAlpha (pSrc))
+ {
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pDst, traps, 0, 0);
+ }
+ else if (maskFormat)
+ {
+ PicturePtr pPicture;
+ BoxRec bounds;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+
+ xDst = traps[0].left.p1.x >> 16;
+ yDst = traps[0].left.p1.y >> 16;
+
+ if (nxagentTrapezoidExtents != NullBox)
+ {
+ memcpy(&bounds, nxagentTrapezoidExtents, sizeof(BoxRec));
+ }
+ else
+ {
+ nxagentTrapezoidExtents = (BoxPtr) malloc(sizeof(BoxRec));
+
+ miTrapezoidBounds (ntrap, traps, &bounds);
+
+ memcpy(nxagentTrapezoidExtents, &bounds, sizeof(BoxRec));
+ }
+
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+ pPicture = miCreateAlphaPicture (pScreen, pDst, maskFormat,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ if (!pPicture)
+ return;
+ for (; ntrap; ntrap--, traps++)
+ (*ps->RasterizeTrapezoid) (pPicture, traps,
+ -bounds.x1, -bounds.y1);
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture (op, pSrc, pPicture, pDst,
+ xRel, yRel, 0, 0, bounds.x1, bounds.y1,
+ bounds.x2 - bounds.x1,
+ bounds.y2 - bounds.y1);
+ FreePicture (pPicture, 0);
+ }
+ else
+ {
+ if (pDst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat (pScreen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat (pScreen, 8, PICT_a8);
+ for (; ntrap; ntrap--, traps++)
+ miTrapezoids (op, pSrc, pDst, maskFormat, xSrc, ySrc, 1, traps);
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c
new file mode 100644
index 000000000..4ea7d2d73
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c
@@ -0,0 +1,654 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+#include "picturestr.h"
+
+#include "Screen.h"
+#include "Pixmaps.h"
+#include "Drawable.h"
+#include "Render.h"
+
+/* prototypes */
+
+PictFormatPtr PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp);
+PicturePtr AllocatePicture (ScreenPtr pScreen);
+PicturePtr CreatePicture (Picture pid,
+ DrawablePtr pDrawable,
+ PictFormatPtr pFormat,
+ Mask vmask,
+ XID *vlist,
+ ClientPtr client,
+ int *error);
+static PicturePtr createSourcePicture(void);
+int FreePicture (void *value, XID pid);
+
+#include "../../render/picture.c"
+
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+void *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual);
+
+void *nxagentMatchingFormats(PictFormatPtr pForm);
+
+void nxagentPictureCreateDefaultFormats(ScreenPtr pScreen, FormatInitRec *formats, int *nformats);
+
+PictFormatPtr
+PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
+{
+ int nformats, f;
+ PictFormatPtr pFormats;
+ FormatInitRec formats[1024];
+ CARD32 format;
+
+ nformats = 0;
+
+ nxagentPictureCreateDefaultFormats(pScreen, formats, &nformats);
+
+ pFormats = (PictFormatPtr) calloc (nformats, sizeof (PictFormatRec));
+ if (!pFormats)
+ return 0;
+ 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;
+ switch (PICT_FORMAT_TYPE(format)) {
+ case PICT_TYPE_ARGB:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+ if (pFormats[f].direct.alphaMask)
+ pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
+ PICT_FORMAT_G(format) +
+ PICT_FORMAT_B(format));
+
+ pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+ pFormats[f].direct.red = (PICT_FORMAT_G(format) +
+ PICT_FORMAT_B(format));
+
+ pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+ pFormats[f].direct.green = PICT_FORMAT_B(format);
+
+ pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+ pFormats[f].direct.blue = 0;
+ break;
+
+ case PICT_TYPE_ABGR:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+ if (pFormats[f].direct.alphaMask)
+ pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
+ PICT_FORMAT_G(format) +
+ PICT_FORMAT_R(format));
+
+ pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+ pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
+ PICT_FORMAT_R(format));
+
+ pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+ pFormats[f].direct.green = PICT_FORMAT_R(format);
+
+ pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+ pFormats[f].direct.red = 0;
+ break;
+
+ case PICT_TYPE_A:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alpha = 0;
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+
+ /* remaining fields already set to zero */
+ break;
+
+ case PICT_TYPE_COLOR:
+ case PICT_TYPE_GRAY:
+ pFormats[f].type = PictTypeIndexed;
+ pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
+ break;
+ }
+
+ 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
+ }
+ }
+ *nformatp = nformats;
+ return pFormats;
+}
+
+PicturePtr
+AllocatePicture (ScreenPtr pScreen)
+{
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ PicturePtr pPicture;
+ char *ptr;
+ DevUnion *ppriv;
+ unsigned int *sizes;
+ unsigned int size;
+ int i;
+
+ pPicture = (PicturePtr) calloc(1, ps->totalPictureSize);
+ if (!pPicture)
+ return 0;
+ ppriv = (DevUnion *)(pPicture + 1);
+ pPicture->devPrivates = ppriv;
+ sizes = ps->PicturePrivateSizes;
+ ptr = (char *)(ppriv + ps->PicturePrivateLen);
+ for (i = ps->PicturePrivateLen; --i >= 0; ppriv++, sizes++)
+ {
+ if ( (size = *sizes) )
+ {
+ ppriv->ptr = (void *)ptr;
+ ptr += size;
+ }
+ else
+ ppriv->ptr = (void *)NULL;
+ }
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+
+ return pPicture;
+}
+
+PicturePtr
+CreatePicture (Picture pid,
+ DrawablePtr pDrawable,
+ PictFormatPtr pFormat,
+ Mask vmask,
+ XID *vlist,
+ ClientPtr client,
+ int *error)
+{
+ PicturePtr pPicture;
+ PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
+
+ pPicture = AllocatePicture (pDrawable->pScreen);
+ if (!pPicture)
+ {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pDrawable = pDrawable;
+ pPicture->pFormat = pFormat;
+ pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
+ if (pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ /*
+ * Let picture always point to the virtual pixmap.
+ * For sure this is not the best way to deal with
+ * the virtual frame-buffer.
+ */
+ pPicture->pDrawable = nxagentVirtualDrawable(pDrawable);
+
+ ++((PixmapPtr)pDrawable)->refcnt;
+ pPicture->pNext = 0;
+ }
+ else
+ {
+ pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
+ SetPictureWindow(((WindowPtr) pDrawable), pPicture);
+ }
+
+ SetPictureToDefaults (pPicture);
+
+ if (vmask)
+ *error = ChangePicture (pPicture, vmask, vlist, 0, client);
+ else
+ *error = Success;
+ if (*error == Success)
+ *error = (*ps->CreatePicture) (pPicture);
+ if (*error != Success)
+ {
+ FreePicture (pPicture, (XID) 0);
+ pPicture = 0;
+ }
+ return pPicture;
+}
+
+PicturePtr
+CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
+{
+ PicturePtr pPicture;
+ pPicture = createSourcePicture();
+ if (!pPicture) {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pSourcePict = (SourcePictPtr) calloc(1, sizeof(PictSolidFill));
+ if (!pPicture->pSourcePict) {
+ *error = BadAlloc;
+ free(pPicture);
+ return 0;
+ }
+ pPicture->pSourcePict->type = SourcePictTypeSolidFill;
+ pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
+ pPicture->pSourcePict->solidFill.fullColor.alpha=color->alpha;
+ pPicture->pSourcePict->solidFill.fullColor.red=color->red;
+ pPicture->pSourcePict->solidFill.fullColor.green=color->green;
+ pPicture->pSourcePict->solidFill.fullColor.blue=color->blue;
+ return pPicture;
+}
+
+static PicturePtr createSourcePicture(void)
+{
+ PicturePtr pPicture;
+
+ 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) calloc(1, 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 = (void *) privPictureRecAddr;
+
+ pPicture -> devPrivates = ppriv;
+
+ nxagentPicturePriv(pPicture) -> picture = 0;
+ }
+
+ pPicture->pDrawable = 0;
+ pPicture->pFormat = 0;
+ pPicture->pNext = 0;
+
+ SetPictureToDefaults(pPicture);
+ return pPicture;
+}
+
+int
+FreePicture (void * value,
+ XID pid)
+{
+ PicturePtr pPicture = (PicturePtr) value;
+
+ if (--pPicture->refcnt == 0)
+ {
+ nxagentDestroyPicture(pPicture);
+
+ if (pPicture->transform)
+ free (pPicture->transform);
+ if (!pPicture->pDrawable) {
+ if (pPicture->pSourcePict) {
+ if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
+ free(pPicture->pSourcePict->linear.stops);
+ free(pPicture->pSourcePict);
+ }
+ } else {
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ if (pPicture->alphaMap)
+ FreePicture ((void *) pPicture->alphaMap, (XID) 0);
+ (*ps->DestroyPicture) (pPicture);
+ (*ps->DestroyPictureClip) (pPicture);
+ if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
+ PicturePtr *pPrev;
+
+ for (pPrev = (PicturePtr *) &((pWindow)->devPrivates[PictureWindowPrivateIndex].ptr);
+ *pPrev;
+ pPrev = &(*pPrev)->pNext)
+ {
+ if (*pPrev == pPicture)
+ {
+ *pPrev = pPicture->pNext;
+ break;
+ }
+ }
+ }
+ else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
+ }
+ }
+ free (pPicture);
+ }
+ return Success;
+}
+
+#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;
+ }
+ }
+
+ free(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)
+{
+ #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/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr_PictSolidFill.h b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr_PictSolidFill.h
new file mode 100644
index 000000000..9cd73db5c
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicturestr_PictSolidFill.h
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * $Id: picturestr.h,v 1.15 2005/12/09 18:35:21 ajax Exp $
+ *
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+/* this header file gets included into Xserver/render/picturestr.h */
+
+#ifndef NX_PICTURESTR_PICTSOLIDFILL_H
+#define NX_PICTURESTR_PICTSOLIDFILL_H 1
+
+
+typedef struct _PictSolidFill {
+ unsigned int type;
+ CARD32 color;
+ xRenderColor fullColor;
+} PictSolidFill, *PictSolidFillPtr;
+
+#endif /* NX_PICTURESTR_PICTSOLIDFILL_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c
new file mode 100644
index 000000000..ee77eb64e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXproperty.c
@@ -0,0 +1,653 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+
+#include "../../dix/property.c"
+
+#include "Options.h"
+#include "Rootless.h"
+#include "Client.h"
+#include "Windows.h"
+
+extern Atom clientCutProperty;
+
+#ifdef NXAGENT_SERVER
+typedef struct
+{
+ CARD32 state;
+ Window icon;
+}
+nxagentWMStateRec;
+#endif
+
+int
+ProcChangeProperty(ClientPtr client)
+{
+ WindowPtr pWin;
+ char format, mode;
+ unsigned long len;
+ int sizeInBytes;
+ int totalSize;
+ int err;
+ REQUEST(xChangePropertyReq);
+
+ REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
+ UpdateCurrentTime();
+ format = stuff->format;
+ mode = stuff->mode;
+ if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+ (mode != PropModePrepend))
+ {
+ client->errorValue = mode;
+ return BadValue;
+ }
+ if ((format != 8) && (format != 16) && (format != 32))
+ {
+ client->errorValue = format;
+ return BadValue;
+ }
+ len = stuff->nUnits;
+ if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
+ return BadLength;
+ sizeInBytes = format>>3;
+ 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,
+ DixWriteAccess);
+ if (!pWin)
+ return(BadWindow);
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+#ifdef XCSECURITY
+ switch (SecurityCheckPropertyAccess(client, pWin, stuff->property,
+ DixWriteAccess))
+ {
+ case SecurityErrorOperation:
+ client->errorValue = stuff->property;
+ return BadAtom;
+ case SecurityIgnoreOperation:
+ return Success;
+ }
+#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
+
+ err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format,
+ (int)mode, len, (void *)&stuff[1], TRUE);
+ if (err != Success)
+ return err;
+ else
+ {
+ if (nxagentOption(Rootless) == 1)
+ {
+ nxagentExportProperty(pWin, stuff->property, stuff->type, (int) format,
+ (int) mode, len, (void *) &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
+ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format,
+ int mode, unsigned long len, void * value,
+ Bool sendevent)
+{
+ PropertyPtr pProp;
+ xEvent event;
+ int sizeInBytes;
+ int totalSize;
+ void * data;
+ int copySize;
+
+ memset(&event, 0, sizeof(xEvent));
+
+ 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);
+ while (pProp)
+ {
+ if (pProp->propertyName == property)
+ break;
+ pProp = pProp->next;
+ }
+ if (!pProp) /* just add to list */
+ {
+ if (!pWin->optional && !MakeWindowOptional (pWin))
+ return(BadAlloc);
+ pProp = (PropertyPtr)malloc(sizeof(PropertyRec));
+ if (!pProp)
+ return(BadAlloc);
+ data = (void *)malloc(totalSize);
+ if (!data && len)
+ {
+ free(pProp);
+ return(BadAlloc);
+ }
+ pProp->propertyName = property;
+ pProp->type = type;
+ pProp->format = format;
+ pProp->data = data;
+ if (len)
+ memmove((char *)data, (char *)value, totalSize);
+ pProp->size = len;
+ pProp->next = pWin->optional->userProps;
+ pWin->optional->userProps = pProp;
+ }
+ else
+ {
+ /* To append or prepend to a property the request format and type
+ must match those of the already defined property. The
+ existing format and type are irrelevant when using the mode
+ "PropModeReplace" since they will be written over. */
+
+ if ((format != pProp->format) && (mode != PropModeReplace))
+ return(BadMatch);
+ if ((pProp->type != type) && (mode != PropModeReplace))
+ return(BadMatch);
+ if (mode == PropModeReplace)
+ {
+ if (totalSize != pProp->size * (pProp->format >> 3))
+ {
+ data = (void *)realloc(pProp->data, totalSize);
+ if (!data && len)
+ return(BadAlloc);
+ pProp->data = data;
+ }
+ if (len)
+ memmove((char *)pProp->data, (char *)value, totalSize);
+ pProp->size = len;
+ pProp->type = type;
+ pProp->format = format;
+ }
+ else if (len == 0)
+ {
+ /* do nothing */
+ }
+ else if (mode == PropModeAppend)
+ {
+ data = (void *)realloc(pProp->data,
+ sizeInBytes * (len + pProp->size));
+ if (!data)
+ return(BadAlloc);
+ pProp->data = data;
+ memmove(&((char *)data)[pProp->size * sizeInBytes],
+ (char *)value,
+ totalSize);
+ pProp->size += len;
+ }
+ else if (mode == PropModePrepend)
+ {
+ data = (void *)malloc(sizeInBytes * (len + pProp->size));
+ if (!data)
+ return(BadAlloc);
+ memmove(&((char *)data)[totalSize], (char *)pProp->data,
+ (int)(pProp->size * sizeInBytes));
+ memmove((char *)data, (char *)value, totalSize);
+ free(pProp->data);
+ pProp->data = data;
+ pProp->size += len;
+ }
+ }
+ if (sendevent)
+ {
+ event.u.u.type = PropertyNotify;
+ event.u.property.window = pWin->drawable.id;
+ event.u.property.state = PropertyNewValue;
+ event.u.property.atom = pProp->propertyName;
+ event.u.property.time = currentTime.milliseconds;
+ DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
+ }
+ return(Success);
+}
+
+/*****************
+ * GetProperty
+ * If type Any is specified, returns the property from the specified
+ * window regardless of its type. If a type is specified, returns the
+ * property only if its type equals the specified type.
+ * If delete is True and a property is returned, the property is also
+ * deleted from the window and a PropertyNotify event is generated on the
+ * window.
+ *****************/
+
+int
+ProcGetProperty(ClientPtr client)
+{
+ PropertyPtr pProp, prevProp;
+ unsigned long n, len, ind;
+ WindowPtr pWin;
+ xGetPropertyReply reply;
+ REQUEST(xGetPropertyReq);
+
+ REQUEST_SIZE_MATCH(xGetPropertyReq);
+
+ if (stuff->delete)
+ UpdateCurrentTime();
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ DixReadAccess);
+ if (!pWin)
+ return BadWindow;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return(BadAtom);
+ }
+ if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
+ {
+ client->errorValue = stuff->delete;
+ return(BadValue);
+ }
+ if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
+ {
+ client->errorValue = stuff->type;
+ return(BadAtom);
+ }
+
+ pProp = wUserProps (pWin);
+ prevProp = (PropertyPtr)NULL;
+ while (pProp)
+ {
+ if (pProp->propertyName == stuff->property)
+ break;
+ prevProp = pProp;
+ pProp = pProp->next;
+ }
+
+ memset(&reply, 0, sizeof(xGetPropertyReply));
+ 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)
+ {
+ nxagentWMStateRec wmState;
+ nxagentWMStateRec *wmsP = &wmState;
+
+ memset(&wmState, 0, sizeof(nxagentWMStateRec));
+ 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);
+
+#ifdef XCSECURITY
+ {
+ Mask access_mode = DixReadAccess;
+
+ if (stuff->delete)
+ access_mode |= DixDestroyAccess;
+ switch(SecurityCheckPropertyAccess(client, pWin, stuff->property,
+ access_mode))
+ {
+ case SecurityErrorOperation:
+ client->errorValue = stuff->property;
+ return BadAtom;;
+ case SecurityIgnoreOperation:
+ return NullPropertyReply(client, pProp->type, pProp->format,
+ &reply);
+ }
+ }
+#endif
+ /* If the request type and actual type don't match. Return the
+ property information, but not the data. */
+
+ if (((stuff->type != pProp->type) &&
+ (stuff->type != AnyPropertyType))
+ )
+ {
+ reply.bytesAfter = pProp->size;
+ reply.format = pProp->format;
+ reply.length = 0;
+ reply.nItems = 0;
+ reply.propertyType = pProp->type;
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+ return(Success);
+ }
+
+/*
+ * Return type, format, value to client
+ */
+ n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
+ ind = stuff->longOffset << 2;
+
+ /* If longOffset is invalid such that it causes "len" to
+ be negative, it's a value error. */
+
+ if (n < ind)
+ {
+ client->errorValue = stuff->longOffset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * stuff->longLength);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.format = pProp->format;
+ reply.length = (len + 3) >> 2;
+ reply.nItems = len / (pProp->format / 8 );
+ reply.propertyType = pProp->type;
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ { /* send the event */
+ xEvent event;
+
+ memset(&event, 0, sizeof(xEvent));
+ 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);
+ }
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+ if (len)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, len,
+ (char *)pProp->data + ind);
+ }
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ { /* delete the Property */
+ if (prevProp == (PropertyPtr)NULL) /* takes care of head */
+ {
+ if (!(pWin->optional->userProps = pProp->next))
+ CheckWindowOptionalNeed (pWin);
+ }
+ else
+ prevProp->next = pProp->next;
+ free(pProp->data);
+ free(pProp);
+ }
+ 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;
+
+ memset(&event, 0, sizeof(xEvent));
+ 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 */
+ if (prevProp == (PropertyPtr)NULL) /* takes care of head */
+ {
+ if (!(pWin->optional->userProps = pProp->next))
+ CheckWindowOptionalNeed (pWin);
+ }
+ else
+ prevProp->next = pProp->next;
+ free(pProp->data);
+ free(pProp);
+ }
+ return(Success);
+}
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXrender.c b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c
new file mode 100644
index 000000000..691b260cf
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXrender.c
@@ -0,0 +1,1730 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+#include "../render/render.c"
+
+#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 NXglyph.c.
+ */
+
+extern
+void GlyphExtents(int nlist, GlyphListPtr list,
+ GlyphPtr *glyphs, BoxPtr extents);
+
+/*
+ * From NXmitrap.c.
+ */
+
+extern
+void miTrapezoidBounds (int ntrap, xTrapezoid *traps, BoxPtr box);
+
+/*
+ * Functions from Render.c.
+ */
+
+extern int nxagentCursorSaveRenderInfo(ScreenPtr, CursorPtr);
+extern void nxagentCursorPostSaveRenderInfo(CursorPtr, ScreenPtr, PicturePtr, int, int);
+extern int nxagentRenderRealizeCursor(ScreenPtr, CursorPtr);
+extern int nxagentCreatePicture(PicturePtr, Mask);
+extern void nxagentChangePicture(PicturePtr, Mask);
+extern int nxagentChangePictureClip(PicturePtr, int, int, xRectangle *, int, int);
+extern void nxagentComposite(CARD8, PicturePtr, PicturePtr, PicturePtr, INT16, INT16,
+ INT16, INT16, INT16, INT16, CARD16, CARD16);
+extern void nxagentCompositeRects(CARD8, PicturePtr, xRenderColor *, int, xRectangle *);
+extern void nxagentCreateGlyphSet(GlyphSetPtr glyphSet);
+extern void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet);
+extern void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph);
+extern void nxagentFreeGlyphSet(GlyphSetPtr glyphSet);
+extern void nxagentSetPictureTransform(PicturePtr pPicture, void * transform);
+extern void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
+ void * params, int nparams);
+extern void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid *traps);
+extern void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color);
+extern void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
+ xPointFixed *p2, int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+extern void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors);
+extern 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 client)
+{
+ RenderClientPtr pRenderClient = GetRenderClient (client);
+ xRenderQueryVersionReply rep;
+ REQUEST(xRenderQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
+
+ pRenderClient->major_version = stuff->majorVersion;
+ pRenderClient->minor_version = stuff->minorVersion;
+
+ memset(&rep, 0, sizeof(xRenderQueryVersionReply));
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = nxagentRenderVersionMajor;
+ rep.minorVersion = nxagentRenderVersionMinor;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.majorVersion);
+ swapl(&rep.minorVersion);
+ }
+ WriteToClient(client, sizeof(xRenderQueryVersionReply), &rep);
+ return (client->noClientException);
+}
+
+static int
+ProcRenderQueryPictFormats (ClientPtr client)
+{
+ RenderClientPtr pRenderClient = GetRenderClient (client);
+ xRenderQueryPictFormatsReply *reply;
+ xPictScreen *pictScreen;
+ xPictDepth *pictDepth;
+ xPictVisual *pictVisual;
+ xPictFormInfo *pictForm;
+ CARD32 *pictSubpixel;
+ ScreenPtr pScreen;
+ VisualPtr pVisual;
+ DepthPtr pDepth;
+ int v, d;
+ PictureScreenPtr ps;
+ PictFormatPtr pFormat;
+ int nformat;
+ int ndepth;
+ int nvisual;
+ int rlength;
+ int s;
+ int numScreens;
+ int numSubpixel;
+
+ extern int nxagentAlphaEnabled;
+/* REQUEST(xRenderQueryPictFormatsReq); */
+
+ REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
+
+#ifdef PANORAMIX
+ if (noPanoramiXExtension)
+ numScreens = screenInfo.numScreens;
+ else
+ numScreens = ((xConnSetup *)ConnectionInfo)->numRoots;
+#else
+ numScreens = screenInfo.numScreens;
+#endif
+ ndepth = nformat = nvisual = 0;
+ for (s = 0; s < numScreens; s++)
+ {
+ pScreen = screenInfo.screens[s];
+ for (d = 0; d < pScreen->numDepths; d++)
+ {
+ pDepth = pScreen->allowedDepths + d;
+ ++ndepth;
+
+ for (v = 0; v < pDepth->numVids; v++)
+ {
+ pVisual = findVisual (pScreen, pDepth->vids[v]);
+ if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual))
+ ++nvisual;
+ }
+ }
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ nformat += ps->nformats;
+ }
+ if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6)
+ numSubpixel = 0;
+ else
+ numSubpixel = numScreens;
+
+ rlength = (sizeof (xRenderQueryPictFormatsReply) +
+ nformat * sizeof (xPictFormInfo) +
+ numScreens * sizeof (xPictScreen) +
+ ndepth * sizeof (xPictDepth) +
+ nvisual * sizeof (xPictVisual) +
+ numSubpixel * sizeof (CARD32));
+ reply = (xRenderQueryPictFormatsReply *) calloc (1, rlength);
+ if (!reply)
+ return BadAlloc;
+ reply->type = X_Reply;
+ reply->sequenceNumber = client->sequence;
+ reply->length = (rlength - sizeof(xGenericReply)) >> 2;
+ reply->numFormats = nformat;
+ reply->numScreens = numScreens;
+ reply->numDepths = ndepth;
+ reply->numVisuals = nvisual;
+ reply->numSubpixel = numSubpixel;
+
+ pictForm = (xPictFormInfo *) (reply + 1);
+
+ for (s = 0; s < numScreens; s++)
+ {
+ pScreen = screenInfo.screens[s];
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ {
+ for (nformat = 0, pFormat = ps->formats;
+ nformat < ps->nformats;
+ nformat++, pFormat++)
+ {
+ pictForm->id = pFormat->id;
+ pictForm->type = pFormat->type;
+ pictForm->depth = pFormat->depth;
+ pictForm->direct.red = pFormat->direct.red;
+ pictForm->direct.redMask = pFormat->direct.redMask;
+ pictForm->direct.green = pFormat->direct.green;
+ pictForm->direct.greenMask = pFormat->direct.greenMask;
+ pictForm->direct.blue = pFormat->direct.blue;
+ pictForm->direct.blueMask = pFormat->direct.blueMask;
+ 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;
+ else
+ pictForm->colormap = None;
+ if (client->swapped)
+ {
+ swapl (&pictForm->id);
+ swaps (&pictForm->direct.red);
+ swaps (&pictForm->direct.redMask);
+ swaps (&pictForm->direct.green);
+ swaps (&pictForm->direct.greenMask);
+ swaps (&pictForm->direct.blue);
+ swaps (&pictForm->direct.blueMask);
+ swaps (&pictForm->direct.alpha);
+ swaps (&pictForm->direct.alphaMask);
+ swapl (&pictForm->colormap);
+ }
+ pictForm++;
+ }
+ }
+ }
+
+ pictScreen = (xPictScreen *) pictForm;
+ for (s = 0; s < numScreens; s++)
+ {
+ pScreen = screenInfo.screens[s];
+ pictDepth = (xPictDepth *) (pictScreen + 1);
+ ndepth = 0;
+ for (d = 0; d < pScreen->numDepths; d++)
+ {
+ pictVisual = (xPictVisual *) (pictDepth + 1);
+ pDepth = pScreen->allowedDepths + d;
+
+ nvisual = 0;
+ for (v = 0; v < pDepth->numVids; v++)
+ {
+ pVisual = findVisual (pScreen, pDepth->vids[v]);
+ if (pVisual && (pFormat = PictureMatchVisual (pScreen,
+ pDepth->depth,
+ pVisual)))
+ {
+ pictVisual->visual = pVisual->vid;
+ pictVisual->format = pFormat->id;
+ if (client->swapped)
+ {
+ swapl (&pictVisual->visual);
+ swapl (&pictVisual->format);
+ }
+ pictVisual++;
+ nvisual++;
+ }
+ }
+ pictDepth->depth = pDepth->depth;
+ pictDepth->nPictVisuals = nvisual;
+ if (client->swapped)
+ {
+ swaps (&pictDepth->nPictVisuals);
+ }
+ ndepth++;
+ pictDepth = (xPictDepth *) pictVisual;
+ }
+ pictScreen->nDepth = ndepth;
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ pictScreen->fallback = ps->fallback->id;
+ else
+ pictScreen->fallback = 0;
+ if (client->swapped)
+ {
+ swapl (&pictScreen->nDepth);
+ swapl (&pictScreen->fallback);
+ }
+ pictScreen = (xPictScreen *) pictDepth;
+ }
+ pictSubpixel = (CARD32 *) pictScreen;
+
+ for (s = 0; s < numSubpixel; s++)
+ {
+ pScreen = screenInfo.screens[s];
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ *pictSubpixel = ps->subpixel;
+ else
+ *pictSubpixel = SubPixelUnknown;
+ if (client->swapped)
+ {
+ swapl (pictSubpixel);
+ }
+ ++pictSubpixel;
+ }
+
+ if (client->swapped)
+ {
+ swaps (&reply->sequenceNumber);
+ swapl (&reply->length);
+ swapl (&reply->numFormats);
+ swapl (&reply->numScreens);
+ swapl (&reply->numDepths);
+ swapl (&reply->numVisuals);
+ swapl (&reply->numSubpixel);
+ }
+ WriteToClient(client, rlength, reply);
+ free (reply);
+ return client->noClientException;
+}
+
+static int
+ProcRenderCreatePicture (ClientPtr client)
+{
+ PicturePtr pPicture;
+ DrawablePtr pDrawable;
+ PictFormatPtr pFormat;
+ int len;
+ int error;
+ REQUEST(xRenderCreatePictureReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
+
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+ SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client,
+ DixWriteAccess);
+ pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
+ stuff->format,
+ PictFormatType,
+ DixReadAccess);
+ if (!pFormat)
+ {
+ client->errorValue = stuff->format;
+ return RenderErrBase + BadPictFormat;
+ }
+ if (pFormat->depth != pDrawable->depth)
+ return BadMatch;
+ len = client->req_len - (sizeof(xRenderCreatePictureReq) >> 2);
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ pPicture = CreatePicture (stuff->pid,
+ pDrawable,
+ pFormat,
+ stuff->mask,
+ (XID *) (stuff + 1),
+ client,
+ &error);
+ if (!pPicture)
+ return error;
+ nxagentCreatePicture(pPicture, stuff -> mask);
+
+ if (!AddResource (stuff->pid, PictureType, (void *)pPicture))
+ return BadAlloc;
+ return Success;
+}
+
+static int
+ProcRenderChangePicture (ClientPtr client)
+{
+ PicturePtr pPicture;
+ REQUEST(xRenderChangePictureReq);
+ int len;
+ int error;
+
+ REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+
+ len = client->req_len - (sizeof(xRenderChangePictureReq) >> 2);
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+
+ error = ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1),
+ (DevUnion *) 0, client);
+
+ nxagentChangePicture(pPicture, stuff->mask);
+
+ return error;
+}
+
+static int
+ProcRenderSetPictureClipRectangles (ClientPtr client)
+{
+ REQUEST(xRenderSetPictureClipRectanglesReq);
+ PicturePtr pPicture;
+ int nr;
+ int result;
+
+ REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ if (!pPicture->pDrawable)
+ return BadDrawable;
+
+ /*
+ * 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
+ return(result);
+}
+
+/*
+ * 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)
+{
+ PicturePtr pSrc, pMask, pDst;
+ REQUEST(xRenderCompositeReq);
+
+ REQUEST_SIZE_MATCH(xRenderCompositeReq);
+ if (!PictOpValid (stuff->op))
+ {
+ client->errorValue = stuff->op;
+ return BadValue;
+ }
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ if (!pDst->pDrawable)
+ return BadDrawable;
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
+ RenderErrBase + BadPicture);
+ VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess,
+ RenderErrBase + BadPicture);
+
+ 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,
+ pDst,
+ stuff->xSrc,
+ stuff->ySrc,
+ stuff->xMask,
+ stuff->yMask,
+ stuff->xDst,
+ 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;
+}
+
+static int
+ProcRenderTrapezoids (ClientPtr client)
+{
+ int ntraps;
+ PicturePtr pSrc, pDst;
+ PictFormatPtr pFormat;
+ REQUEST(xRenderTrapezoidsReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
+ if (!PictOpValid (stuff->op))
+ {
+ client->errorValue = stuff->op;
+ return BadValue;
+ }
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
+ RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ if (!pDst->pDrawable)
+ return BadDrawable;
+ if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+ return BadMatch;
+ if (stuff->maskFormat)
+ {
+ pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
+ stuff->maskFormat,
+ PictFormatType,
+ DixReadAccess);
+ if (!pFormat)
+ {
+ client->errorValue = stuff->maskFormat;
+ return RenderErrBase + BadPictFormat;
+ }
+ }
+ else
+ pFormat = 0;
+ ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq);
+ if (ntraps % sizeof (xTrapezoid))
+ return BadLength;
+ ntraps /= sizeof (xTrapezoid);
+ if (ntraps)
+ {
+ if (pFormat != NULL)
+ {
+ nxagentTrapezoidExtents = (BoxPtr) malloc(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)
+ {
+ free(nxagentTrapezoidExtents);
+
+ nxagentTrapezoidExtents = NullBox;
+ }
+ }
+
+ return client->noClientException;
+}
+
+static int
+ProcRenderCreateGlyphSet (ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ PictFormatPtr format;
+ int f;
+ REQUEST(xRenderCreateGlyphSetReq);
+
+ REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
+
+ LEGAL_NEW_RESOURCE(stuff->gsid, client);
+ format = (PictFormatPtr) SecurityLookupIDByType (client,
+ stuff->format,
+ PictFormatType,
+ DixReadAccess);
+ if (!format)
+ {
+ client->errorValue = stuff->format;
+ return RenderErrBase + BadPictFormat;
+ }
+ switch (format->depth) {
+ case 1:
+ f = GlyphFormat1;
+ break;
+ case 4:
+ f = GlyphFormat4;
+ break;
+ case 8:
+ f = GlyphFormat8;
+ break;
+ case 16:
+ f = GlyphFormat16;
+ break;
+ case 32:
+ f = GlyphFormat32;
+ break;
+ default:
+ return BadMatch;
+ }
+ if (format->type != PictTypeDirect)
+ return BadMatch;
+ glyphSet = AllocateGlyphSet (f, format);
+ if (!glyphSet)
+ return BadAlloc;
+ if (!AddResource (stuff->gsid, GlyphSetType, (void *)glyphSet))
+ return BadAlloc;
+
+ nxagentCreateGlyphSet(glyphSet);
+
+ return Success;
+}
+
+static int
+ProcRenderReferenceGlyphSet (ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderReferenceGlyphSetReq);
+
+ REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
+
+ LEGAL_NEW_RESOURCE(stuff->gsid, client);
+
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ stuff->existing,
+ GlyphSetType,
+ DixWriteAccess);
+ if (!glyphSet)
+ {
+ client->errorValue = stuff->existing;
+ return RenderErrBase + BadGlyphSet;
+ }
+ glyphSet->refcnt++;
+
+ nxagentReferenceGlyphSet(glyphSet);
+
+ if (!AddResource (stuff->gsid, GlyphSetType, (void *)glyphSet))
+ return BadAlloc;
+ return client->noClientException;
+}
+
+static int
+ProcRenderFreeGlyphSet (ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderFreeGlyphSetReq);
+
+ REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ stuff->glyphset,
+ GlyphSetType,
+ DixDestroyAccess);
+ if (!glyphSet)
+ {
+ client->errorValue = stuff->glyphset;
+ return RenderErrBase + BadGlyphSet;
+ }
+
+ nxagentFreeGlyphSet(glyphSet);
+
+ FreeResource (stuff->glyphset, RT_NONE);
+ return client->noClientException;
+}
+
+static int
+ProcRenderFreeGlyphs (ClientPtr client)
+{
+ REQUEST(xRenderFreeGlyphsReq);
+ GlyphSetPtr glyphSet;
+ int nglyph;
+ CARD32 *gids;
+ CARD32 glyph;
+
+ REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ stuff->glyphset,
+ GlyphSetType,
+ DixWriteAccess);
+ if (!glyphSet)
+ {
+ client->errorValue = stuff->glyphset;
+ return RenderErrBase + BadGlyphSet;
+ }
+ nglyph = ((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)) >> 2;
+ gids = (CARD32 *) (stuff + 1);
+
+ nxagentFreeGlyphs(glyphSet, gids, nglyph);
+
+ while (nglyph-- > 0)
+ {
+ glyph = *gids++;
+ if (!DeleteGlyph (glyphSet, glyph))
+ {
+ client->errorValue = glyph;
+ return RenderErrBase + BadGlyph;
+ }
+ }
+ return client->noClientException;
+}
+
+typedef struct XGlyphElt8{
+ GlyphSet glyphset;
+ _Xconst char *chars;
+ int nchars;
+ int xOff;
+ int yOff;
+} XGlyphElt8;
+
+static int
+ProcRenderCompositeGlyphs (ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ GlyphSet gs;
+ PicturePtr pSrc, pDst;
+ PictFormatPtr pFormat;
+ GlyphListRec listsLocal[NLOCALDELTA];
+ GlyphListPtr lists, listsBase;
+ GlyphPtr glyphsLocal[NLOCALGLYPH];
+ Glyph glyph;
+ GlyphPtr *glyphs, *glyphsBase;
+ xGlyphElt *elt;
+ CARD8 *buffer, *end;
+ int nglyph;
+ int nlist;
+ int space;
+ int size;
+ int n;
+
+ XGlyphElt8 *elements, *elementsBase;
+
+ REQUEST(xRenderCompositeGlyphsReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
+
+ switch (stuff->renderReqType) {
+ default: size = 1; break;
+ case X_RenderCompositeGlyphs16: size = 2; break;
+ case X_RenderCompositeGlyphs32: size = 4; break;
+ }
+
+ if (!PictOpValid (stuff->op))
+ {
+ client->errorValue = stuff->op;
+ return BadValue;
+ }
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
+ RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ if (!pDst->pDrawable)
+ return BadDrawable;
+ if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
+ return BadMatch;
+ if (stuff->maskFormat)
+ {
+ pFormat = (PictFormatPtr) SecurityLookupIDByType (client,
+ stuff->maskFormat,
+ PictFormatType,
+ DixReadAccess);
+ if (!pFormat)
+ {
+ client->errorValue = stuff->maskFormat;
+ return RenderErrBase + BadPictFormat;
+ }
+ }
+ else
+ pFormat = 0;
+
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ stuff->glyphset,
+ GlyphSetType,
+ DixReadAccess);
+ if (!glyphSet)
+ {
+ client->errorValue = stuff->glyphset;
+ return RenderErrBase + BadGlyphSet;
+ }
+
+ buffer = (CARD8 *) (stuff + 1);
+ end = (CARD8 *) stuff + (client->req_len << 2);
+ nglyph = 0;
+ nlist = 0;
+ while (buffer + sizeof (xGlyphElt) < end)
+ {
+ elt = (xGlyphElt *) buffer;
+ buffer += sizeof (xGlyphElt);
+
+ if (elt->len == 0xff)
+ {
+ buffer += 4;
+ }
+ else
+ {
+ nlist++;
+ nglyph += elt->len;
+ space = size * elt->len;
+ if (space & 3)
+ space += 4 - (space & 3);
+ buffer += space;
+ }
+ }
+ if (nglyph <= NLOCALGLYPH)
+ glyphsBase = glyphsLocal;
+ else
+ {
+ glyphsBase = (GlyphPtr *) malloc (nglyph * sizeof (GlyphPtr));
+ if (!glyphsBase)
+ return BadAlloc;
+ }
+ if (nlist <= NLOCALDELTA)
+ listsBase = listsLocal;
+ else
+ {
+ listsBase = (GlyphListPtr) malloc (nlist * sizeof (GlyphListRec));
+ if (!listsBase)
+ return BadAlloc;
+ }
+
+ elementsBase = malloc(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;
+ buffer += sizeof (xGlyphElt);
+
+ 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));
+ glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
+ gs,
+ GlyphSetType,
+ DixReadAccess);
+ if (!glyphSet)
+ {
+ client->errorValue = gs;
+ if (glyphsBase != glyphsLocal)
+ free (glyphsBase);
+ if (listsBase != listsLocal)
+ free (listsBase);
+ return RenderErrBase + BadGlyphSet;
+ }
+ }
+ buffer += 4;
+ }
+ else
+ {
+ lists->xOff = elt->deltax;
+ 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--)
+ {
+ if (buffer + size <= end)
+ {
+ switch (size) {
+ case 1:
+ glyph = *((CARD8 *)buffer); break;
+ case 2:
+ glyph = *((CARD16 *)buffer); break;
+ case 4:
+ default:
+ glyph = *((CARD32 *)buffer); break;
+ }
+ if ((*glyphs = FindGlyph (glyphSet, glyph)))
+ {
+ lists->len++;
+ glyphs++;
+ }
+ }
+ buffer += size;
+ }
+ space = size * elt->len;
+ if (space & 3)
+ buffer += 4 - (space & 3);
+ lists++;
+ elements++;
+ }
+ }
+ if (buffer > end)
+ return BadLength;
+
+ /*
+ * 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) malloc(sizeof(BoxRec));
+
+ GlyphExtents(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);
+ }
+
+ free(nxagentGlyphsExtents);
+ nxagentGlyphsExtents = NullBox;
+
+ if (glyphsBase != glyphsLocal)
+ free (glyphsBase);
+ if (listsBase != listsLocal)
+ free (listsBase);
+
+ free(elementsBase);
+
+ return client->noClientException;
+}
+
+static int
+ProcRenderFillRectangles (ClientPtr client)
+{
+ PicturePtr pDst;
+ int things;
+ REQUEST(xRenderFillRectanglesReq);
+
+ REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq);
+ if (!PictOpValid (stuff->op))
+ {
+ client->errorValue = stuff->op;
+ return BadValue;
+ }
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ if (!pDst->pDrawable)
+ return BadDrawable;
+
+ things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
+ if (things & 4)
+ return(BadLength);
+ things >>= 3;
+
+ CompositeRects (stuff->op,
+ pDst,
+ &stuff->color,
+ things,
+ (xRectangle *) &stuff[1]);
+
+ ValidatePicture (pDst);
+ nxagentCompositeRects(stuff -> op,
+ pDst,
+ &stuff -> color,
+ things,
+ (xRectangle *) &stuff[1]);
+
+ return client->noClientException;
+}
+
+static int
+ProcRenderCreateCursor (ClientPtr client)
+{
+ REQUEST(xRenderCreateCursorReq);
+ PicturePtr pSrc;
+ ScreenPtr pScreen;
+ unsigned short width, height;
+ CARD32 *argbbits, *argb;
+ unsigned char *srcbits, *srcline;
+ unsigned char *mskbits, *mskline;
+ int stride;
+ int x, y;
+ int nbytes_mono;
+ CursorMetricRec cm;
+ CursorPtr pCursor;
+ CARD32 twocolor[3];
+ int ncolor;
+
+ RealizeCursorProcPtr saveRealizeCursor;
+
+ REQUEST_SIZE_MATCH (xRenderCreateCursorReq);
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
+ RenderErrBase + BadPicture);
+ if (!pSrc->pDrawable)
+ return BadDrawable;
+ pScreen = pSrc->pDrawable->pScreen;
+ width = pSrc->pDrawable->width;
+ height = pSrc->pDrawable->height;
+ if (height && width > UINT32_MAX/(height*sizeof(CARD32)))
+ return BadAlloc;
+ if ( stuff->x > width
+ || stuff->y > height )
+ return (BadMatch);
+ argbbits = malloc (width * height * sizeof (CARD32));
+ if (!argbbits)
+ return (BadAlloc);
+
+ stride = BitmapBytePad(width);
+ nbytes_mono = stride*height;
+ srcbits = (unsigned char *)malloc(nbytes_mono);
+ if (!srcbits)
+ {
+ free (argbbits);
+ return (BadAlloc);
+ }
+ mskbits = (unsigned char *)malloc(nbytes_mono);
+ if (!mskbits)
+ {
+ free(argbbits);
+ free(srcbits);
+ return (BadAlloc);
+ }
+ bzero ((char *) mskbits, nbytes_mono);
+ bzero ((char *) srcbits, nbytes_mono);
+
+ if (pSrc->format == PICT_a8r8g8b8)
+ {
+ (*pScreen->GetImage) (pSrc->pDrawable,
+ 0, 0, width, height, ZPixmap,
+ 0xffffffff, (void *) argbbits);
+ }
+ else
+ {
+ PixmapPtr pPixmap;
+ PicturePtr pPicture;
+ PictFormatPtr pFormat;
+ int error;
+
+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
+ if (!pFormat)
+ {
+ free (argbbits);
+ free (srcbits);
+ free (mskbits);
+ return (BadImplementation);
+ }
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pPixmap)
+ {
+ free (argbbits);
+ free (srcbits);
+ free (mskbits);
+ return (BadAlloc);
+ }
+ pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0,
+ client, &error);
+ if (!pPicture)
+ {
+ free (argbbits);
+ free (srcbits);
+ free (mskbits);
+ return error;
+ }
+ (*pScreen->DestroyPixmap) (pPixmap);
+ CompositePicture (PictOpSrc,
+ pSrc, 0, pPicture,
+ 0, 0, 0, 0, 0, 0, width, height);
+ (*pScreen->GetImage) (pPicture->pDrawable,
+ 0, 0, width, height, ZPixmap,
+ 0xffffffff, (void *) argbbits);
+ FreePicture (pPicture, 0);
+ }
+ /*
+ * Check whether the cursor can be directly supported by
+ * the core cursor code
+ */
+ ncolor = 0;
+ argb = argbbits;
+ for (y = 0; ncolor <= 2 && y < height; y++)
+ {
+ for (x = 0; ncolor <= 2 && x < width; x++)
+ {
+ CARD32 p = *argb++;
+ CARD32 a = (p >> 24);
+
+ if (a == 0) /* transparent */
+ continue;
+ if (a == 0xff) /* opaque */
+ {
+ int n;
+ for (n = 0; n < ncolor; n++)
+ if (p == twocolor[n])
+ break;
+ if (n == ncolor)
+ twocolor[ncolor++] = p;
+ }
+ else
+ ncolor = 3;
+ }
+ }
+
+ /*
+ * Convert argb image to two plane cursor
+ */
+ srcline = srcbits;
+ mskline = mskbits;
+ argb = argbbits;
+ for (y = 0; y < height; y++)
+ {
+ for (x = 0; x < width; x++)
+ {
+ CARD32 p = *argb++;
+
+ if (ncolor <= 2)
+ {
+ CARD32 a = ((p >> 24));
+
+ SetBit (mskline, x, a != 0);
+ SetBit (srcline, x, a != 0 && p == twocolor[0]);
+ }
+ else
+ {
+ CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255;
+ CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255;
+ CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)];
+ /* Set mask from dithered alpha value */
+ SetBit(mskline, x, a > d);
+ /* Set src from dithered intensity value */
+ SetBit(srcline, x, a > d && i <= d);
+ }
+ }
+ srcline += stride;
+ mskline += stride;
+ }
+ /*
+ * Dither to white and black if the cursor has more than two colors
+ */
+ if (ncolor > 2)
+ {
+ twocolor[0] = 0xff000000;
+ twocolor[1] = 0xffffffff;
+ }
+ else
+ {
+ free (argbbits);
+ argbbits = 0;
+ }
+
+#define GetByte(p,s) (((p) >> (s)) & 0xff)
+#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8))
+
+ cm.width = width;
+ 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),
+ GetColor(twocolor[0], 0),
+ GetColor(twocolor[1], 16),
+ GetColor(twocolor[1], 8),
+ GetColor(twocolor[1], 0));
+
+ 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, (void *)pCursor))
+ return (client->noClientException);
+ return BadAlloc;
+}
+
+static int
+ProcRenderSetPictureTransform (ClientPtr client)
+{
+ REQUEST(xRenderSetPictureTransformReq);
+ PicturePtr pPicture;
+ int result;
+
+ REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform);
+
+ nxagentSetPictureTransform(pPicture, &stuff->transform);
+
+ if (client->noClientException != Success)
+ return(client->noClientException);
+ else
+ return(result);
+}
+
+static int
+ProcRenderSetPictureFilter (ClientPtr client)
+{
+ REQUEST (xRenderSetPictureFilterReq);
+ PicturePtr pPicture;
+ int result;
+ xFixed *params;
+ int nparams;
+ char *name;
+
+ REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
+ RenderErrBase + BadPicture);
+ name = (char *) (stuff + 1);
+ 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;
+}
+
+static int
+ProcRenderCreateAnimCursor (ClientPtr client)
+{
+ REQUEST(xRenderCreateAnimCursorReq);
+ CursorPtr *cursors;
+ CARD32 *deltas;
+ CursorPtr pCursor;
+ int ncursor;
+ xAnimCursorElt *elt;
+ int i;
+ int ret;
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+ if (client->req_len & 1)
+ return BadLength;
+ ncursor = (client->req_len - (SIZEOF(xRenderCreateAnimCursorReq) >> 2)) >> 1;
+ cursors = malloc (ncursor * (sizeof (CursorPtr) + sizeof (CARD32)));
+ if (!cursors)
+ return BadAlloc;
+ deltas = (CARD32 *) (cursors + ncursor);
+ elt = (xAnimCursorElt *) (stuff + 1);
+ for (i = 0; i < ncursor; i++)
+ {
+ cursors[i] = (CursorPtr)SecurityLookupIDByType(client, elt->cursor,
+ RT_CURSOR, DixReadAccess);
+ if (!cursors[i])
+ {
+ free (cursors);
+ client->errorValue = elt->cursor;
+ return BadCursor;
+ }
+ deltas[i] = elt->delay;
+ elt++;
+ }
+ ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor);
+ free (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, (void *)pCursor))
+ return client->noClientException;
+ return BadAlloc;
+}
+
+static int ProcRenderCreateSolidFill(ClientPtr client)
+{
+ PicturePtr pPicture;
+ int error = 0;
+ REQUEST(xRenderCreateSolidFillReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
+
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+ pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
+ if (!pPicture)
+ return error;
+ /* AGENT SERVER */
+
+ nxagentRenderCreateSolidFill(pPicture, &stuff -> color);
+
+ /* AGENT SERVER */
+ if (!AddResource (stuff->pid, PictureType, (void *)pPicture))
+ return BadAlloc;
+ return Success;
+}
+
+static int ProcRenderCreateLinearGradient (ClientPtr client)
+{
+ PicturePtr pPicture;
+ int len;
+ int error = 0;
+ xFixed *stops;
+ xRenderColor *colors;
+ REQUEST(xRenderCreateLinearGradientReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
+
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+ len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
+ if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+ if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+
+ stops = (xFixed *)(stuff + 1);
+ colors = (xRenderColor *)(stops + stuff->nStops);
+
+ pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2,
+ 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, (void *)pPicture))
+ return BadAlloc;
+ return Success;
+}
+
+static int ProcRenderCreateRadialGradient (ClientPtr client)
+{
+ PicturePtr pPicture;
+ int len;
+ int error = 0;
+ xFixed *stops;
+ xRenderColor *colors;
+ REQUEST(xRenderCreateRadialGradientReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
+
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+ len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
+ if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+
+ stops = (xFixed *)(stuff + 1);
+ colors = (xRenderColor *)(stops + stuff->nStops);
+
+ pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer,
+ stuff->inner_radius, stuff->outer_radius,
+ 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, (void *)pPicture))
+ return BadAlloc;
+ return Success;
+}
+
+static int ProcRenderCreateConicalGradient (ClientPtr client)
+{
+ PicturePtr pPicture;
+ int len;
+ int error = 0;
+ xFixed *stops;
+ xRenderColor *colors;
+ REQUEST(xRenderCreateConicalGradientReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
+
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+ len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
+ if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor)))
+ return BadLength;
+
+ stops = (xFixed *)(stuff + 1);
+ colors = (xRenderColor *)(stops + stuff->nStops);
+
+ pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle,
+ 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, (void *)pPicture))
+ return BadAlloc;
+ return Success;
+}
+
+
+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)
+ {
+ #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;
+}
+
+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)
+ {
+ /*
+ * 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;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXresource.c b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c
new file mode 100644
index 000000000..a564d84b9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXresource.c
@@ -0,0 +1,595 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 panoramix components contained the following notice */
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+/* $TOG: resource.c /main/41 1998/02/09 14:20:31 kaleb $ */
+
+/* Routines to manage various kinds of resources:
+ *
+ * CreateNewResourceType, CreateNewResourceClass, InitClientResources,
+ * FakeClientID, AddResource, FreeResource, FreeClientResources,
+ * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
+ */
+
+/*
+ * A resource ID is a 32 bit quantity, the upper 2 bits of which are
+ * off-limits for client-visible resources. The next 8 bits are
+ * used as client ID, and the low 22 bits come from the client.
+ * A resource ID is "hashed" by extracting and xoring subfields
+ * (varying with the size of the hash table).
+ *
+ * It is sometimes necessary for the server to create an ID that looks
+ * like it belongs to a client. This ID, however, must not be one
+ * the client actually can create, or we have the potential for conflict.
+ * The 31st bit of the ID is reserved for the server's use for this
+ * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
+ * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
+ * resource "owned" by the client.
+ */
+
+#include "../../dix/resource.c"
+
+#include "Agent.h"
+#include "Font.h"
+#include "Pixmaps.h"
+#include "GCs.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#ifdef NXAGENT_SERVER
+static int nxagentResChangedFlag = 0;
+#endif
+
+#ifdef NXAGENT_SERVER
+int nxagentFindClientResource(int client, RESTYPE type, void * 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, void * 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 /* NXAGENT_SERVER */
+
+Bool
+AddResource(XID id, RESTYPE type, void * value)
+{
+ int client;
+ register ClientResourceRec *rrec;
+ register ResourcePtr res, *head;
+
+ client = CLIENT_ID(id);
+ rrec = &clientTable[client];
+ if (!rrec->buckets)
+ {
+ ErrorF("AddResource(%lx, %lx, %lx), client=%d \n",
+ (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);
+ head = &rrec->resources[Hash(client, id)];
+ res = (ResourcePtr)malloc(sizeof(ResourceRec));
+ if (!res)
+ {
+ (*DeleteFuncs[type & TypeMask])(value, id);
+ return FALSE;
+ }
+ res->next = *head;
+ res->id = id;
+ res->type = type;
+ 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;
+}
+
+void
+FreeResource(XID id, RESTYPE skipDeleteFuncType)
+{
+ int cid;
+ register ResourcePtr res;
+ register ResourcePtr *prev, *head;
+ register int *eltptr;
+ 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)];
+ eltptr = &clientTable[cid].elements;
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id)
+ {
+ RESTYPE rtype = res->type;
+ *prev = res->next;
+ elements = --*eltptr;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ if (rtype != skipDeleteFuncType)
+ (*DeleteFuncs[rtype & TypeMask])(res->value, res->id);
+ free(res);
+ if (*eltptr != elements)
+ prev = head; /* prev may no longer be valid */
+ gotOne = TRUE;
+ }
+ else
+ prev = &res->next;
+ }
+ }
+ if (!gotOne)
+ ErrorF("Freeing resource id=%lX which isn't there.\n",
+ (unsigned long)id);
+}
+
+
+void
+FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
+{
+ int cid;
+ register ResourcePtr res;
+ register ResourcePtr *prev, *head;
+ if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets)
+ {
+ head = &clientTable[cid].resources[Hash(cid, id)];
+
+ prev = head;
+ while ( (res = *prev) )
+ {
+ if (res->id == id && res->type == type)
+ {
+ *prev = res->next;
+ #ifdef NXAGENT_SERVER
+ nxagentResChangedFlag = 1;
+ #endif
+ if (!skipFree)
+ (*DeleteFuncs[type & TypeMask])(res->value, res->id);
+ free(res);
+ break;
+ }
+ else
+ prev = &res->next;
+ }
+ }
+}
+
+/* Note: if func adds or deletes resources, then func can get called
+ * more than once for some resources. If func adds new resources,
+ * func might or might not get called for them. func cannot both
+ * add and delete an equal number of resources!
+ */
+
+void
+FindClientResourcesByType(
+ ClientPtr client,
+ RESTYPE type,
+ FindResType func,
+ void * cdata
+){
+ register ResourcePtr *resources;
+ register ResourcePtr this, next;
+ 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++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ 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 */
+ }
+ }
+ }
+}
+
+void
+FindAllClientResources(
+ ClientPtr client,
+ FindAllRes func,
+ void * cdata
+){
+ register ResourcePtr *resources;
+ register ResourcePtr this, next;
+ 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++)
+ {
+ for (this = resources[i]; this; this = next)
+ {
+ 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 */
+ }
+ }
+}
+
+
+void *
+LookupClientResourceComplex(
+ ClientPtr client,
+ RESTYPE type,
+ FindComplexResType func,
+ void * cdata
+){
+ ResourcePtr *resources;
+ 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
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXshm.c b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c
new file mode 100644
index 000000000..2ffca8066
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXshm.c
@@ -0,0 +1,547 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/************************************************************
+
+Copyright 1989, 1998 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+********************************************************/
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
+
+
+#include <nx-X11/X.h>
+#include "Trap.h"
+#include "Agent.h"
+
+#include "Drawable.h"
+#include "Pixmaps.h"
+
+#include "../../Xext/shm.c"
+
+/*
+ * 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);
+
+void
+ShmExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ int i;
+
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+ if (!CheckForShmSyscall())
+ {
+ ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
+ return;
+ }
+#endif
+
+ if (nxagentOption(SharedMemory) == False)
+ {
+ return;
+ }
+
+ sharedPixmaps = xFalse;
+ pixmapFormat = 0;
+ {
+ 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))
+ {
+ sharedPixmaps = xFalse;
+ pixmapFormat = 0;
+ }
+ }
+ if (!pixmapFormat)
+ pixmapFormat = ZPixmap;
+ if (sharedPixmaps)
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap;
+ screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
+ }
+#ifdef PIXPRIV
+ shmPixmapPrivate = AllocatePixmapPrivateIndex();
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (!AllocatePixmapPrivate(screenInfo.screens[i],
+ shmPixmapPrivate, 0))
+ return;
+ }
+#endif
+ }
+ }
+ ShmSegType = CreateNewResourceType(ShmDetachSegment);
+ if (ShmSegType &&
+ (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
+ ProcShmDispatch, SProcShmDispatch,
+ ShmResetProc, StandardMinorOpcode)))
+ {
+ ShmReqCode = (unsigned char)extEntry->base;
+ ShmCompletionCode = extEntry->eventBase;
+ BadShmSegCode = extEntry->errorBase;
+ EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
+ }
+}
+
+static void
+miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
+ DrawablePtr dst;
+ GCPtr pGC;
+ int depth, w, h, sx, sy, sw, sh, dx, dy;
+ unsigned int format;
+ char *data;
+{
+ 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,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pmap)
+ {
+ nxagentShmTrap = 1;
+ FreeScratchGC(putGC);
+ return;
+ }
+ ValidateGC((DrawablePtr)pmap, putGC);
+ (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0,
+ (format == XYPixmap) ? XYPixmap : ZPixmap, data);
+ FreeScratchGC(putGC);
+ if (format == XYBitmap)
+ (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
+ dx, dy, 1L);
+ else
+ (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
+ dx, dy);
+ (*pmap->drawable.pScreen->DestroyPixmap)(pmap);
+ nxagentShmTrap = 1;
+}
+
+static void
+fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
+ DrawablePtr dst;
+ GCPtr pGC;
+ int depth, w, h, sx, sy, sw, sh, dx, dy;
+ 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;
+
+ pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
+ BitsPerPixel(depth), PixmapBytePad(w, depth), (void *)data);
+ if (!pPixmap)
+ return;
+ if (format == XYBitmap)
+ (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC,
+ sx, sy, sw, sh, dx, dy, 1L);
+ 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 = calloc(1, 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);
+
+ free(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);
+ }
+}
+
+static int
+ProcShmPutImage(client)
+ register ClientPtr client;
+{
+ register GCPtr pGC;
+ register DrawablePtr pDraw;
+ long length;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmPutImageReq);
+
+ REQUEST_SIZE_MATCH(xShmPutImageReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
+ if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
+ return BadValue;
+ if (stuff->format == XYBitmap)
+ {
+ if (stuff->depth != 1)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, 1);
+ }
+ else if (stuff->format == XYPixmap)
+ {
+ if (pDraw->depth != stuff->depth)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, 1);
+ length *= stuff->depth;
+ }
+ else if (stuff->format == ZPixmap)
+ {
+ if (pDraw->depth != stuff->depth)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, stuff->depth);
+ }
+ else
+ {
+ client->errorValue = stuff->format;
+ return BadValue;
+ }
+
+ /*
+ * There's a potential integer overflow in this check:
+ * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+ * client);
+ * the version below ought to avoid it
+ */
+ if (stuff->totalHeight != 0 &&
+ length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
+ client->errorValue = stuff->totalWidth;
+ return BadValue;
+ }
+ if (stuff->srcX > stuff->totalWidth)
+ {
+ client->errorValue = stuff->srcX;
+ return BadValue;
+ }
+ if (stuff->srcY > stuff->totalHeight)
+ {
+ client->errorValue = stuff->srcY;
+ return BadValue;
+ }
+ if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
+ {
+ client->errorValue = stuff->srcWidth;
+ return BadValue;
+ }
+ if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
+ {
+ client->errorValue = stuff->srcHeight;
+ return BadValue;
+ }
+
+ #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)
+ {
+ xShmCompletionEvent ev;
+
+ memset(&ev, 0, sizeof(xShmCompletionEvent));
+ ev.type = ShmCompletionCode;
+ ev.drawable = stuff->drawable;
+ ev.sequenceNumber = client->sequence;
+ ev.minorEvent = X_ShmPutImage;
+ ev.majorEvent = ShmReqCode;
+ ev.shmseg = stuff->shmseg;
+ ev.offset = stuff->offset;
+ WriteEventsToClient(client, 1, (xEvent *) &ev);
+ }
+
+ return (client->noClientException);
+}
+
+
+static PixmapPtr
+fbShmCreatePixmap (pScreen, width, height, depth, addr)
+ ScreenPtr pScreen;
+ int width;
+ int height;
+ int depth;
+ char *addr;
+{
+ register PixmapPtr pPixmap;
+
+ nxagentShmPixmapTrap = 1;
+
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0);
+
+ if (!pPixmap)
+ {
+ nxagentShmPixmapTrap = 0;
+
+ return NullPixmap;
+ }
+
+ #ifdef TEST
+ fprintf(stderr,"fbShmCreatePixmap: Width [%d] Height [%d] Depth [%d] Hint[%d]\n", width, height, depth, 0);
+ #endif
+
+ if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
+ BitsPerPixel(depth), PixmapBytePad(width, depth), (void *)addr))
+ {
+ #ifdef WARNING
+ fprintf(stderr,"fbShmCreatePixmap: Return Null Pixmap.\n");
+ #endif
+
+ (*pScreen->DestroyPixmap)(pPixmap);
+
+ nxagentShmPixmapTrap = 0;
+
+ return NullPixmap;
+ }
+
+ nxagentShmPixmapTrap = 0;
+
+ return pPixmap;
+}
+
+
+static int
+ProcShmDispatch (client)
+ 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:
+ return ProcShmQueryVersion(client);
+ case X_ShmAttach:
+ return ProcShmAttach(client);
+ 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 )
+ {
+ result = ProcPanoramiXShmPutImage(client);
+
+ nxagentShmTrap = 0;
+
+ return result;
+ }
+#endif
+
+ 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 )
+ return ProcPanoramiXShmGetImage(client);
+#endif
+ return ProcShmGetImage(client);
+ case X_ShmCreatePixmap:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXShmCreatePixmap(client);
+#endif
+ return ProcShmCreatePixmap(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcShmDispatch (client)
+ 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:
+ return SProcShmQueryVersion(client);
+ case X_ShmAttach:
+ return SProcShmAttach(client);
+ case X_ShmDetach:
+ return SProcShmDetach(client);
+ case X_ShmPutImage:
+ {
+ 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:
+ return SProcShmCreatePixmap(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c
new file mode 100644
index 000000000..7de25ca28
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c
@@ -0,0 +1,1127 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+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 THE OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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 panoramix components contained the following notice */
+/*****************************************************************
+
+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.
+
+******************************************************************/
+
+
+#include "selection.h"
+
+#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"
+
+/* prototypes (only MakeRootTile() required here) */
+
+static void MakeRootTile(WindowPtr pWin);
+
+#include "../../dix/window.c"
+
+extern Bool nxagentWMIsRunning;
+extern Bool nxagentScreenTrap;
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+WindowPtr nxagentRootTileWindow;
+
+void nxagentClearSplash(WindowPtr pW)
+{
+ ScreenPtr pScreen;
+
+ 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);
+}
+
+static void
+MakeRootTile(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ GCPtr pGC;
+ unsigned char back[128];
+ int len = BitmapBytePad(sizeof(long));
+ register unsigned char *from, *to;
+ register int i, j;
+
+ pWin->background.pixmap = (*pScreen->CreatePixmap)(pScreen, 4, 4,
+ pScreen->rootDepth, 0);
+
+ pWin->backgroundState = BackgroundPixmap;
+ pGC = GetScratchGC(pScreen->rootDepth, pScreen);
+ if (!pWin->background.pixmap || !pGC)
+ FatalError("could not create root tile");
+
+ {
+ CARD32 attributes[2];
+
+ attributes[0] = pScreen->whitePixel;
+ attributes[1] = pScreen->blackPixel;
+
+ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes);
+ }
+
+ ValidateGC((DrawablePtr)pWin->background.pixmap, pGC);
+
+ from = (screenInfo.bitmapBitOrder == LSBFirst) ? _back_lsb : _back_msb;
+ to = back;
+
+ for (i = 4; i > 0; i--, from++)
+ for (j = len; j > 0; j--)
+ *to++ = *from;
+
+ if (blackRoot)
+ bzero(back, sizeof(back));
+
+ (*pGC->ops->PutImage)((DrawablePtr)pWin->background.pixmap, pGC, 1,
+ 0, 0, len, 4, 0, XYBitmap, (char *)back);
+
+ FreeScratchGC(pGC);
+
+ nxagentRootTileWindow = pWin;
+}
+
+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 screenInfo.screens as
+ * in the following snippet:
+ *
+ * for (i = 0; i < screenInfo.numScreens; i++)
+ * InitRootWindow(screenInfo.screens[i]->root);
+ *
+ * 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
+}
+
+/*****
+ * DeleteWindow
+ * Deletes child of window then window itself
+ * If wid is None, don't send any events
+ *****/
+
+int
+DeleteWindow(void * value, XID wid)
+ {
+ register WindowPtr pParent;
+ register WindowPtr pWin = (WindowPtr)value;
+ xEvent event;
+
+ UnmapWindow(pWin, FALSE);
+
+ CrushTree(pWin);
+
+ pParent = pWin->parent;
+ if (wid && pParent && SubStrSend(pWin, pParent))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = DestroyNotify;
+ event.u.destroyNotify.window = pWin->drawable.id;
+ DeliverEvents(pWin, &event, 1, NullWindow);
+ }
+
+ FreeWindowResources(pWin);
+ if (pParent)
+ {
+ if (pParent->firstChild == pWin)
+ pParent->firstChild = pWin->nextSib;
+ if (pParent->lastChild == pWin)
+ pParent->lastChild = pWin->prevSib;
+ if (pWin->nextSib)
+ pWin->nextSib->prevSib = pWin->prevSib;
+ if (pWin->prevSib)
+ pWin->prevSib->nextSib = pWin->nextSib;
+ }
+
+ if (pWin -> optional &&
+ pWin -> optional -> colormap &&
+ pWin -> parent)
+ {
+ nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen);
+ }
+
+ free(pWin);
+ return Success;
+}
+
+/* XXX need to retile border on each window with ParentRelative origin */
+void
+ResizeChildrenWinSize(register WindowPtr pWin, int dx, int dy, int dw, int dh)
+{
+ register ScreenPtr pScreen;
+ register WindowPtr pSib, pChild;
+ Bool resized = (dw || dh);
+
+ pScreen = pWin->drawable.pScreen;
+
+ for (pSib = pWin->firstChild; pSib; pSib = pSib->nextSib)
+ {
+ if (resized && (pSib->winGravity > NorthWestGravity))
+ {
+ int cwsx, cwsy;
+
+ cwsx = pSib->origin.x;
+ cwsy = pSib->origin.y;
+ GravityTranslate (cwsx, cwsy, cwsx - dx, cwsy - dy, dw, dh,
+ pSib->winGravity, &cwsx, &cwsy);
+ if (cwsx != pSib->origin.x || cwsy != pSib->origin.y)
+ {
+ xEvent event;
+
+ event.u.u.type = GravityNotify;
+ event.u.gravity.window = pSib->drawable.id;
+ event.u.gravity.x = cwsx - wBorderWidth (pSib);
+ event.u.gravity.y = cwsy - wBorderWidth (pSib);
+ DeliverEvents (pSib, &event, 1, NullWindow);
+ pSib->origin.x = cwsx;
+ pSib->origin.y = cwsy;
+ }
+ }
+ pSib->drawable.x = pWin->drawable.x + pSib->origin.x;
+ pSib->drawable.y = pWin->drawable.y + pSib->origin.y;
+ SetWinSize (pSib);
+ SetBorderSize (pSib);
+
+ /*
+ * 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) )
+ {
+ while (1)
+ {
+ pChild->drawable.x = pChild->parent->drawable.x +
+ pChild->origin.x;
+ pChild->drawable.y = pChild->parent->drawable.y +
+ pChild->origin.y;
+ SetWinSize (pChild);
+ SetBorderSize (pChild);
+
+ (*pScreen->PositionWindow)(pChild, pChild->drawable.x,
+ pChild->drawable.y);
+
+ if (pChild->firstChild)
+ {
+ pChild = pChild->firstChild;
+ continue;
+ }
+ while (!pChild->nextSib && (pChild != pSib))
+ pChild = pChild->parent;
+ if (pChild == pSib)
+ break;
+ pChild = pChild->nextSib;
+ }
+ }
+ }
+}
+
+/*****
+ * ConfigureWindow
+ *****/
+
+int
+ConfigureWindow(register WindowPtr pWin, register Mask mask, XID *vlist, ClientPtr client)
+{
+#define RESTACK_WIN 0
+#define MOVE_WIN 1
+#define RESIZE_WIN 2
+#define REBORDER_WIN 3
+ register WindowPtr pSib = NullWindow;
+ register WindowPtr pParent = pWin->parent;
+ Window sibwid = 0;
+ Mask index2, tmask;
+ register XID *pVlist;
+ short x, y, beforeX, beforeY;
+ unsigned short w = pWin->drawable.width,
+ h = pWin->drawable.height,
+ bw = pWin->borderWidth;
+ int action, smode = Above;
+ xEvent event;
+
+ if ((pWin->drawable.class == InputOnly) && (mask & IllegalInputOnlyConfigureMask))
+ return(BadMatch);
+
+ if ((mask & CWSibling) && !(mask & CWStackMode))
+ return(BadMatch);
+
+ pVlist = vlist;
+
+ if (pParent)
+ {
+ x = pWin->drawable.x - pParent->drawable.x - (int)bw;
+ y = pWin->drawable.y - pParent->drawable.y - (int)bw;
+ }
+ else
+ {
+ x = pWin->drawable.x;
+ y = pWin->drawable.y;
+ }
+ beforeX = x;
+ beforeY = y;
+ action = RESTACK_WIN;
+ if ((mask & (CWX | CWY)) && (!(mask & (CWHeight | CWWidth))))
+ {
+ GET_INT16(CWX, x);
+ GET_INT16(CWY, y);
+ action = MOVE_WIN;
+ }
+ /* or should be resized */
+ else if (mask & (CWX | CWY | CWWidth | CWHeight))
+ {
+ GET_INT16(CWX, x);
+ GET_INT16(CWY, y);
+ GET_CARD16(CWWidth, w);
+ GET_CARD16 (CWHeight, h);
+ if (!w || !h)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ action = RESIZE_WIN;
+ }
+ tmask = mask & ~ChangeMask;
+ while (tmask)
+ {
+ index2 = (Mask)lowbit (tmask);
+ tmask &= ~index2;
+ switch (index2)
+ {
+ case CWBorderWidth:
+ GET_CARD16(CWBorderWidth, bw);
+ break;
+ case CWSibling:
+ sibwid = (Window ) *pVlist;
+ pVlist++;
+ pSib = (WindowPtr )SecurityLookupIDByType(client, sibwid,
+ RT_WINDOW, DixReadAccess);
+ if (!pSib)
+ {
+ client->errorValue = sibwid;
+ return(BadWindow);
+ }
+ if (pSib->parent != pParent)
+ return(BadMatch);
+ if (pSib == pWin)
+ return(BadMatch);
+ break;
+ case CWStackMode:
+ GET_CARD8(CWStackMode, smode);
+ if ((smode != TopIf) && (smode != BottomIf) &&
+ (smode != Opposite) && (smode != Above) && (smode != Below))
+ {
+ client->errorValue = smode;
+ return(BadValue);
+ }
+ break;
+ default:
+ client->errorValue = mask;
+ return(BadValue);
+ }
+ }
+ /* root really can't be reconfigured, so just return */
+ if (!pParent)
+ return Success;
+
+ /* 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,
+ w + (bw << 1), h + (bw << 1), smode);
+ else
+ pSib = pWin->nextSib;
+
+
+ if ((!pWin->overrideRedirect) &&
+ (RedirectSend(pParent)
+ ))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = ConfigureRequest;
+ event.u.configureRequest.window = pWin->drawable.id;
+ if (mask & CWSibling)
+ event.u.configureRequest.sibling = sibwid;
+ else
+ event.u.configureRequest.sibling = None;
+ if (mask & CWStackMode)
+ event.u.u.detail = smode;
+ else
+ event.u.u.detail = Above;
+ event.u.configureRequest.x = x;
+ event.u.configureRequest.y = y;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
+ event.u.configureRequest.x += panoramiXdataPtr[0].x;
+ event.u.configureRequest.y += panoramiXdataPtr[0].y;
+ }
+#endif
+ event.u.configureRequest.width = w;
+ event.u.configureRequest.height = h;
+ event.u.configureRequest.borderWidth = bw;
+ event.u.configureRequest.valueMask = mask;
+ event.u.configureRequest.parent = pParent->drawable.id;
+ if (MaybeDeliverEventsToClient(pParent, &event, 1,
+ SubstructureRedirectMask, client) == 1)
+ return(Success);
+ }
+ if (action == RESIZE_WIN)
+ {
+ Bool size_change = (w != pWin->drawable.width)
+ || (h != pWin->drawable.height);
+ if (size_change && ((pWin->eventMask|wOtherEventMasks(pWin)) & ResizeRedirectMask))
+ {
+ xEvent eventT;
+ memset(&eventT, 0, sizeof(xEvent));
+ eventT.u.u.type = ResizeRequest;
+ eventT.u.resizeRequest.window = pWin->drawable.id;
+ eventT.u.resizeRequest.width = w;
+ eventT.u.resizeRequest.height = h;
+ if (MaybeDeliverEventsToClient(pWin, &eventT, 1,
+ ResizeRedirectMask, client) == 1)
+ {
+ /* if event is delivered, leave the actual size alone. */
+ w = pWin->drawable.width;
+ h = pWin->drawable.height;
+ size_change = FALSE;
+ }
+ }
+ if (!size_change)
+ {
+ if (mask & (CWX | CWY))
+ action = MOVE_WIN;
+ else if (mask & (CWStackMode | CWBorderWidth))
+ action = RESTACK_WIN;
+ else /* really nothing to do */
+ return(Success) ;
+ }
+ }
+
+ if (action == RESIZE_WIN)
+ /* we've already checked whether there's really a size change */
+ goto ActuallyDoSomething;
+ if ((mask & CWX) && (x != beforeX))
+ goto ActuallyDoSomething;
+ if ((mask & CWY) && (y != beforeY))
+ goto ActuallyDoSomething;
+ if ((mask & CWBorderWidth) && (bw != wBorderWidth (pWin)))
+ goto ActuallyDoSomething;
+ if (mask & CWStackMode)
+ {
+#ifndef ROOTLESS
+ /* See above for why we always reorder in rootless mode. */
+ if (pWin->nextSib != pSib)
+#endif
+ goto ActuallyDoSomething;
+ }
+ return(Success);
+
+ActuallyDoSomething:
+ if (SubStrSend(pWin, pParent))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = ConfigureNotify;
+ event.u.configureNotify.window = pWin->drawable.id;
+ if (pSib)
+ event.u.configureNotify.aboveSibling = pSib->drawable.id;
+ else
+ event.u.configureNotify.aboveSibling = None;
+ event.u.configureNotify.x = x;
+ event.u.configureNotify.y = y;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && (!pParent || !pParent->parent)) {
+ event.u.configureNotify.x += panoramiXdataPtr[0].x;
+ event.u.configureNotify.y += panoramiXdataPtr[0].y;
+ }
+#endif
+ event.u.configureNotify.width = w;
+ event.u.configureNotify.height = h;
+ event.u.configureNotify.borderWidth = bw;
+ event.u.configureNotify.override = pWin->overrideRedirect;
+ DeliverEvents(pWin, &event, 1, NullWindow);
+ }
+ if (mask & CWBorderWidth)
+ {
+ if (action == RESTACK_WIN)
+ {
+ action = MOVE_WIN;
+ pWin->borderWidth = bw;
+ }
+ else if ((action == MOVE_WIN) &&
+ (beforeX + wBorderWidth (pWin) == x + (int)bw) &&
+ (beforeY + wBorderWidth (pWin) == y + (int)bw))
+ {
+ action = REBORDER_WIN;
+ (*pWin->drawable.pScreen->ChangeBorderWidth)(pWin, bw);
+ }
+ else
+ pWin->borderWidth = bw;
+ }
+ if (action == MOVE_WIN)
+ (*pWin->drawable.pScreen->MoveWindow)(pWin, x, y, pSib,
+ (mask & CWBorderWidth) ? VTOther : VTMove);
+ else if (action == RESIZE_WIN)
+ (*pWin->drawable.pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
+ else if (mask & CWStackMode)
+ ReflectStackChange(pWin, pSib, VTOther);
+
+ if (action != RESTACK_WIN)
+ CheckCursorConfinement(pWin);
+
+ nxagentFlushConfigureWindow();
+
+ return(Success);
+#undef RESTACK_WIN
+#undef MOVE_WIN
+#undef RESIZE_WIN
+#undef REBORDER_WIN
+}
+
+/*****
+ * ReparentWindow
+ *****/
+
+int
+ReparentWindow(register WindowPtr pWin, register WindowPtr pParent,
+ int x, int y, ClientPtr client)
+{
+ WindowPtr pPrev, pPriorParent;
+ Bool WasMapped = (Bool)(pWin->mapped);
+ xEvent event;
+ int bw = wBorderWidth (pWin);
+ register ScreenPtr pScreen;
+
+ pScreen = pWin->drawable.pScreen;
+ if (TraverseTree(pWin, CompareWIDs, (void *)&pParent->drawable.id) == WT_STOPWALKING)
+ return(BadMatch);
+ if (!MakeWindowOptional(pWin))
+ return(BadAlloc);
+
+ if (WasMapped)
+ UnmapWindow(pWin, FALSE);
+
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = ReparentNotify;
+ event.u.reparent.window = pWin->drawable.id;
+ event.u.reparent.parent = pParent->drawable.id;
+ event.u.reparent.x = x;
+ event.u.reparent.y = y;
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && !pParent->parent) {
+ event.u.reparent.x += panoramiXdataPtr[0].x;
+ event.u.reparent.y += panoramiXdataPtr[0].y;
+ }
+#endif
+ event.u.reparent.override = pWin->overrideRedirect;
+ DeliverEvents(pWin, &event, 1, pParent);
+
+ /* take out of sibling chain */
+
+ pPriorParent = pPrev = pWin->parent;
+ if (pPrev->firstChild == pWin)
+ pPrev->firstChild = pWin->nextSib;
+ if (pPrev->lastChild == pWin)
+ pPrev->lastChild = pWin->prevSib;
+
+ if (pWin->nextSib)
+ pWin->nextSib->prevSib = pWin->prevSib;
+ if (pWin->prevSib)
+ pWin->prevSib->nextSib = pWin->nextSib;
+
+ /* insert at begining of pParent */
+ pWin->parent = pParent;
+ pPrev = RealChildHead(pParent);
+
+ if (pWin->parent == screenInfo.screens[0]->root)
+ {
+ nxagentSetTopLevelEventMask(pWin);
+ }
+
+ if (pPrev)
+ {
+ pWin->nextSib = pPrev->nextSib;
+ if (pPrev->nextSib)
+ pPrev->nextSib->prevSib = pWin;
+ else
+ pParent->lastChild = pWin;
+ pPrev->nextSib = pWin;
+ pWin->prevSib = pPrev;
+ }
+ else
+ {
+ pWin->nextSib = pParent->firstChild;
+ pWin->prevSib = NullWindow;
+ if (pParent->firstChild)
+ pParent->firstChild->prevSib = pWin;
+ else
+ pParent->lastChild = pWin;
+ pParent->firstChild = pWin;
+ }
+
+ pWin->origin.x = x + bw;
+ pWin->origin.y = y + bw;
+ pWin->drawable.x = x + bw + pParent->drawable.x;
+ pWin->drawable.y = y + bw + pParent->drawable.y;
+
+ /* clip to parent */
+ SetWinSize (pWin);
+ SetBorderSize (pWin);
+
+ if (pScreen->ReparentWindow)
+ (*pScreen->ReparentWindow)(pWin, pPriorParent);
+
+ (*pScreen->PositionWindow)(pWin, pWin->drawable.x, pWin->drawable.y);
+
+ ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
+
+ CheckWindowOptionalNeed(pWin);
+
+ if (WasMapped)
+ MapWindow(pWin, client);
+ RecalculateDeliverableEvents(pWin);
+ return(Success);
+}
+
+/*****
+ * MapWindow
+ * If some other client has selected SubStructureReDirect on the parent
+ * and override-redirect is xFalse, then a MapRequest event is generated,
+ * but the window remains unmapped. Otherwise, the window is mapped and a
+ * MapNotify event is generated.
+ *****/
+
+int
+MapWindow(register WindowPtr pWin, ClientPtr client)
+{
+ register ScreenPtr pScreen;
+
+ register WindowPtr pParent;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+
+ #ifdef TEST
+ if (nxagentWindowTopLevel(pWin))
+ {
+ fprintf(stderr, "MapWindow: pWin [%p] client [%p]\n", pWin, client);
+ }
+ #endif
+
+ if (pWin->mapped)
+ return(Success);
+
+#ifdef XCSECURITY
+ /* don't let an untrusted client map a child-of-trusted-window, InputOnly
+ * window; too easy to steal device input
+ */
+ if ( (client->trustLevel != XSecurityClientTrusted) &&
+ (pWin->drawable.class == InputOnly) &&
+ (wClient(pWin->parent)->trustLevel == XSecurityClientTrusted) )
+ return Success;
+#endif
+
+ pScreen = pWin->drawable.pScreen;
+ if ( (pParent = pWin->parent) )
+ {
+ xEvent event;
+ Bool anyMarked;
+
+ if ((!pWin->overrideRedirect) &&
+ (RedirectSend(pParent)
+ ))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = MapRequest;
+ event.u.mapRequest.window = pWin->drawable.id;
+ event.u.mapRequest.parent = pParent->drawable.id;
+
+ if (MaybeDeliverEventsToClient(pParent, &event, 1,
+ SubstructureRedirectMask, client) == 1)
+ return(Success);
+ }
+
+ pWin->mapped = TRUE;
+ if (SubStrSend(pWin, pParent))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = MapNotify;
+ event.u.mapNotify.window = pWin->drawable.id;
+ event.u.mapNotify.override = pWin->overrideRedirect;
+ DeliverEvents(pWin, &event, 1, NullWindow);
+ }
+
+ if (!pParent->realized)
+ return(Success);
+ RealizeTree(pWin);
+ if (pWin->viewable)
+ {
+ anyMarked = (*pScreen->MarkOverlappedWindows)(pWin, pWin,
+ &pLayerWin);
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib);
+ }
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked)
+ {
+ (*pScreen->ValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ }
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pLayerWin, VTMap);
+ }
+ WindowsRestructured ();
+ }
+ else
+ {
+ RegionRec temp;
+
+ pWin->mapped = TRUE;
+ pWin->realized = TRUE; /* for roots */
+ pWin->viewable = pWin->drawable.class == InputOutput;
+ /* We SHOULD check for an error value here XXX */
+ (*pScreen->RealizeWindow)(pWin);
+ if (pScreen->ClipNotify)
+ (*pScreen->ClipNotify) (pWin, 0, 0);
+ if (pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(NullWindow, pWin, VTMap);
+ RegionNull(&temp);
+ RegionCopy(&temp, &pWin->clipList);
+ (*pScreen->WindowExposures) (pWin, &temp, NullRegion);
+ RegionUninit(&temp);
+ }
+
+ nxagentFlushConfigureWindow();
+
+ return(Success);
+}
+
+/*****
+ * UnmapWindow
+ * If the window is already unmapped, this request has no effect.
+ * Otherwise, the window is unmapped and an UnMapNotify event is
+ * generated. Cannot unmap a root window.
+ *****/
+
+int
+UnmapWindow(register WindowPtr pWin, Bool fromConfigure)
+{
+ register WindowPtr pParent;
+ xEvent event;
+ Bool wasRealized = (Bool)pWin->realized;
+ Bool wasViewable = (Bool)pWin->viewable;
+ 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))
+ {
+ memset(&event, 0, sizeof(xEvent));
+ event.u.u.type = UnmapNotify;
+ event.u.unmapNotify.window = pWin->drawable.id;
+ event.u.unmapNotify.fromConfigure = fromConfigure;
+ DeliverEvents(pWin, &event, 1, NullWindow);
+ }
+ if (wasViewable && !fromConfigure)
+ {
+ pWin->valdata = UnmapValData;
+ (*pScreen->MarkOverlappedWindows)(pWin, pWin->nextSib, &pLayerWin);
+ (*pScreen->MarkWindow)(pLayerWin->parent);
+ }
+ pWin->mapped = FALSE;
+ if (wasRealized)
+ UnrealizeTree(pWin, fromConfigure);
+ if (wasViewable)
+ {
+ if (!fromConfigure)
+ {
+ (*pScreen->ValidateTree)(pLayerWin->parent, pWin, VTUnmap);
+ (*pScreen->HandleExposures)(pLayerWin->parent);
+ }
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ if ( (*pScreen->ChangeSaveUnder)(pLayerWin, pWin->nextSib) )
+ {
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pWin->nextSib);
+ }
+ }
+ pWin->DIXsaveUnder = FALSE;
+#endif /* DO_SAVE_UNDERS */
+ if (!fromConfigure && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
+ }
+ if (wasRealized && !fromConfigure)
+ WindowsRestructured ();
+ return(Success);
+}
+
+void
+SaveScreens(int on, int mode)
+{
+ int i;
+ int what;
+ int type;
+
+ if (on == SCREEN_SAVER_FORCER)
+ {
+ UpdateCurrentTimeIf();
+ lastDeviceEventTime = currentTime;
+ if (mode == ScreenSaverReset)
+ what = SCREEN_SAVER_OFF;
+ else
+ what = SCREEN_SAVER_ON;
+ type = what;
+ }
+ else
+ {
+ what = on;
+ type = what;
+ if (what == screenIsSaved)
+ type = SCREEN_SAVER_CYCLE;
+ }
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (on == SCREEN_SAVER_FORCER)
+ (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i], on);
+ if (savedScreenInfo[i].ExternalScreenSaver)
+ {
+ 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;
+ switch (type) {
+ case SCREEN_SAVER_OFF:
+ if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
+ {
+ (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
+ what);
+ }
+ else if (HasSaverWindow (i))
+ {
+ savedScreenInfo[i].pWindow = NullWindow;
+ FreeResource(savedScreenInfo[i].wid, RT_NONE);
+ }
+ break;
+ case SCREEN_SAVER_CYCLE:
+ if (savedScreenInfo[i].blanked == SCREEN_IS_TILED)
+ {
+ WindowPtr pWin = savedScreenInfo[i].pWindow;
+ /* make it look like screen saver is off, so that
+ * NotClippedByChildren will compute a clip list
+ * for the root window, so miPaintWindow works
+ */
+ screenIsSaved = SCREEN_SAVER_OFF;
+#ifndef NOLOGOHACK
+ if (logoScreenSaver)
+ (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, FALSE);
+#endif
+ (*pWin->drawable.pScreen->MoveWindow)(pWin,
+ (short)(-(rand() % RANDOM_WIDTH)),
+ (short)(-(rand() % RANDOM_WIDTH)),
+ pWin->nextSib, VTMove);
+#ifndef NOLOGOHACK
+ if (logoScreenSaver)
+ DrawLogo(pWin);
+#endif
+ screenIsSaved = SCREEN_SAVER_ON;
+ }
+ /*
+ * Call the DDX saver in case it wants to do something
+ * at cycle time
+ */
+ else if (savedScreenInfo[i].blanked == SCREEN_IS_BLANKED)
+ {
+ (* screenInfo.screens[i]->SaveScreen) (screenInfo.screens[i],
+ type);
+ }
+ break;
+ case SCREEN_SAVER_ON:
+ if (ScreenSaverBlanking != DontPreferBlanking)
+ {
+ if ((* screenInfo.screens[i]->SaveScreen)
+ (screenInfo.screens[i], what))
+ {
+ savedScreenInfo[i].blanked = SCREEN_IS_BLANKED;
+ continue;
+ }
+ if ((ScreenSaverAllowExposures != DontAllowExposures) &&
+ TileScreenSaver(i, SCREEN_IS_BLACK))
+ {
+ savedScreenInfo[i].blanked = SCREEN_IS_BLACK;
+ continue;
+ }
+ }
+ if ((ScreenSaverAllowExposures != DontAllowExposures) &&
+ TileScreenSaver(i, SCREEN_IS_TILED))
+ {
+ savedScreenInfo[i].blanked = SCREEN_IS_TILED;
+ }
+ else
+ savedScreenInfo[i].blanked = SCREEN_ISNT_SAVED;
+ break;
+ }
+ }
+ screenIsSaved = what;
+ if (mode == ScreenSaverReset)
+ SetScreenSaverTimer();
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c
new file mode 100644
index 000000000..ee19c28d0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/NXxvdisp.c
@@ -0,0 +1,245 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/***********************************************************
+Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+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 names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL 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.
+
+******************************************************************/
+
+#if !defined(__sun) && !defined(__CYGWIN__)
+
+#include "Trap.h"
+
+#include "../../Xext/xvdisp.c"
+
+#undef TEST
+#undef DEBUG
+
+/*
+** ProcXvDispatch
+**
+**
+**
+*/
+
+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: 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)
+ result = (XineramaXvPutVideo(client));
+ else
+#endif
+ result = (ProcXvPutVideo(client));
+ break;
+ case xv_PutStill:
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ result = (XineramaXvPutStill(client));
+ else
+#endif
+ 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)
+ result = (XineramaXvStopVideo(client));
+ else
+#endif
+ result = (ProcXvStopVideo(client));
+ break;
+ case xv_SetPortAttribute:
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ result = (XineramaXvSetPortAttribute(client));
+ else
+#endif
+ 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)
+ result = (XineramaXvPutImage(client));
+ else
+#endif
+ result = (ProcXvPutImage(client));
+ break;
+#ifdef MITSHM
+ case xv_ShmPutImage:
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension)
+ result = (XineramaXvShmPutImage(client));
+ else
+#endif
+ result = (ProcXvShmPutImage(client));
+ break;
+#endif
+ 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);
+ result = (BadImplementation); break;
+ }
+ else
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, 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: 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: result = (SProcXvShmPutImage(client)); break;
+#endif
+ 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);
+ result = (BadImplementation); break;
+ }
+ else
+ {
+ SendErrorToClient(client, XvReqCode, stuff->data, 0, 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;
+}
+#endif /* !defined(__sun) && !defined(__CYGWIN__) */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.c b/nx-X11/programs/Xserver/hw/nxagent/Options.c
new file mode 100644
index 000000000..978f3ab95
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.c
@@ -0,0 +1,210 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "X.h"
+
+#include "Agent.h"
+#include "Args.h"
+#include "Options.h"
+#include "Utils.h"
+
+/*
+ * Instead of having a single options repository
+ * data could be attached to the display or the
+ * screen. The macro nxagentOption() should make
+ * the transition simple.
+ */
+
+AgentOptionsRec nxagentOptions;
+
+AgentOptionsRec nxagentOptionsBackup;
+
+AgentOptionsPtr nxagentOptionsPtr = &nxagentOptions;
+
+/*
+ * If this is set, print the geometry in the block handler.
+ */
+
+unsigned int nxagentPrintGeometryFlags = 0;
+/*
+ * This must be called at startup to initialize
+ * the options repository to the default values.
+ */
+
+void nxagentInitOptions()
+{
+ nxagentOptions.LinkType = UNDEFINED;
+
+ nxagentOptions.Desktop = UNDEFINED;
+ nxagentOptions.Persistent = 1;
+ nxagentOptions.Rootless = UNDEFINED;
+ nxagentOptions.Fullscreen = UNDEFINED;
+ nxagentOptions.NoRootlessExit = False;
+
+ nxagentOptions.X = 0;
+ nxagentOptions.Y = 0;
+ nxagentOptions.Width = 0;
+ nxagentOptions.Height = 0;
+ nxagentOptions.BorderWidth = 0;
+
+ nxagentOptions.WMBorderWidth = -1;
+ nxagentOptions.WMTitleHeight = -1;
+
+ nxagentOptions.SavedX = 0;
+ nxagentOptions.SavedY = 0;
+ nxagentOptions.SavedWidth = 0;
+ nxagentOptions.SavedHeight = 0;
+
+ nxagentOptions.Timeout = 0;
+
+ nxagentOptions.Nested = 0;
+
+ nxagentOptions.BackingStore = BackingStoreUndefined;
+
+ nxagentOptions.Clipboard = ClipboardBoth;
+
+ nxagentOptions.SharedMemory = 1;
+
+ nxagentOptions.SharedPixmaps = 1;
+
+ nxagentOptions.DeviceControl = 0;
+
+ nxagentOptions.DeviceControlUserDefined = 0;
+
+ nxagentOptions.ResetKeyboardAtResume = 1;
+
+ nxagentOptions.Reset = 0;
+
+ nxagentOptions.RootX = 0;
+ nxagentOptions.RootY = 0;
+ nxagentOptions.RootWidth = 0;
+ nxagentOptions.RootHeight = 0;
+
+ nxagentOptions.ViewportXSpan = 0;
+ nxagentOptions.ViewportYSpan = 0;
+
+ #ifndef __CYGWIN32__
+
+ nxagentOptions.DesktopResize = 1;
+
+ #else
+
+ nxagentOptions.DesktopResize = 0;
+
+ #endif
+
+ nxagentOptions.Ratio = DONT_SCALE;
+ nxagentOptions.XRatio = DONT_SCALE;
+ nxagentOptions.YRatio = DONT_SCALE;
+
+ nxagentOptions.FloatRatio = 1.0;
+ nxagentOptions.FloatXRatio = 1.0;
+ nxagentOptions.FloatYRatio = 1.0;
+
+ nxagentOptions.UseDamage = 1;
+
+ nxagentOptions.Binder = UNDEFINED;
+ nxagentOptions.BinderOptions = NULL;
+
+ nxagentOptions.Xdmcp = 0;
+
+ nxagentOptions.DisplayLatency = 0;
+ nxagentOptions.DisplayBuffer = UNDEFINED;
+ nxagentOptions.DisplayCoalescence = 0;
+
+ nxagentOptions.Composite = 1;
+
+ nxagentOptions.IgnoreVisibility = 0;
+
+ nxagentOptions.ViewOnly = 0;
+
+ nxagentOptions.Adaptive = 0;
+
+ nxagentOptions.Streaming = 0;
+
+ nxagentOptions.DeferLevel = UNDEFINED;
+ nxagentOptions.DeferTimeout = 200;
+
+ nxagentOptions.TileWidth = UNDEFINED;
+ nxagentOptions.TileHeight = UNDEFINED;
+
+ nxagentOptions.Menu = 1;
+
+ nxagentOptions.ClientOs = UNDEFINED;
+
+ nxagentOptions.InhibitXkb = 1;
+
+ nxagentOptions.CopyBufferSize = COPY_UNLIMITED;
+
+ nxagentOptions.ImageRateLimit = 0;
+
+ nxagentOptions.Xinerama = 1;
+
+ nxagentOptions.SleepTime = DEFAULT_SLEEP_TIME;
+
+ nxagentOptions.ReconnectTolerance = DEFAULT_TOLERANCE;
+}
+
+/*
+ * This is called at session reconnection
+ * to reset some options to their default
+ * values. The reason to avoid calling the
+ * nxagentInitOptions() is that not all the
+ * options can change value when reconnec-
+ * ting.
+ */
+
+void nxagentResetOptions()
+{
+ if (nxagentLockDeferLevel == 0)
+ {
+ nxagentOptions.DeferLevel = UNDEFINED;
+ }
+
+ nxagentOptions.DeferTimeout = 200;
+
+ nxagentOptions.TileWidth = UNDEFINED;
+ nxagentOptions.TileHeight = UNDEFINED;
+
+ nxagentOptions.WMBorderWidth = -1;
+ nxagentOptions.WMTitleHeight = -1;
+}
+
+void nxagentSaveOptions()
+{
+ memcpy(&nxagentOptionsBackup, &nxagentOptions, sizeof(AgentOptionsRec));
+}
+
+void nxagentRestoreOptions()
+{
+ nxagentOptions.DeferLevel = nxagentOptionsBackup.DeferLevel;
+ nxagentOptions.DeferTimeout = nxagentOptionsBackup.DeferTimeout;
+
+ nxagentOptions.TileWidth = nxagentOptionsBackup.TileWidth;
+ nxagentOptions.TileHeight = nxagentOptionsBackup.TileHeight;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Options.h b/nx-X11/programs/Xserver/hw/nxagent/Options.h
new file mode 100644
index 000000000..20616a90b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Options.h
@@ -0,0 +1,479 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Options_H__
+#define __Options_H__
+
+#ifndef True
+#define True 1
+#endif
+
+#ifndef False
+#define False 0
+#endif
+
+#define UNDEFINED -1
+#define COPY_UNLIMITED -1
+#define DEFAULT_SLEEP_TIME 50
+
+extern unsigned int nxagentPrintGeometryFlags;
+
+typedef enum _BackingStoreMode
+{
+ BackingStoreUndefined = -1,
+ BackingStoreNever,
+ BackingStoreWhenRequested,
+ BackingStoreForce
+
+} BackingStoreMode;
+
+typedef enum _ClipboardMode
+{
+ ClipboardBoth,
+ ClipboardClient,
+ ClipboardServer,
+ ClipboardNone
+
+} ClipboardMode;
+
+typedef enum _ClientOsType
+{
+ ClientOsWinnt = 0,
+ ClientOsLinux,
+ ClientOsSolaris,
+ ClientOsMac
+
+} ClientOsType;
+
+typedef enum _ToleranceChecksMode
+{
+ ToleranceChecksStrict = 0,
+ ToleranceChecksSafe = 1,
+ ToleranceChecksRisky = 2,
+ ToleranceChecksBypass = 3
+} ToleranceChecksMode;
+
+
+#define DEFAULT_TOLERANCE ToleranceChecksStrict
+
+/*
+ * Set of options affecting agent operations.
+ */
+
+typedef struct _AgentOptions
+{
+ /*
+ * Link type of the NX connection or none,
+ * if this is a direct X11 connection.
+ */
+
+ int LinkType;
+
+ /*
+ * Is agent running in desktop mode? This
+ * is presently the default.
+ */
+
+ int Desktop;
+
+ /*
+ * True if user activated rootless mode.
+ */
+
+ int Rootless;
+
+ /*
+ * True for shadow mode.
+ */
+
+ int Shadow;
+
+ /*
+ * True if user activated persistent mode.
+ */
+
+ int Persistent;
+
+ /*
+ * True if user activated fullscreen mode.
+ */
+
+ int Fullscreen;
+
+ /*
+ * True if the fullscreen NX session will
+ * extend on all available screens.
+ */
+
+ int AllScreens;
+
+ /*
+ * Set to the auto-disconnect timeout, if
+ * the user activated this feature.
+ */
+
+ int Timeout;
+
+ /*
+ * Geometry of the agent's window.
+ */
+
+ int X;
+ int Y;
+ int Width;
+ int Height;
+ int BorderWidth;
+
+ /*
+ * Geometry of the agent's window in window
+ * mode. Used to restore window size when
+ * switching back to window mode from full-
+ * screen.
+ */
+
+ int WMBorderWidth;
+ int WMTitleHeight;
+
+ int SavedX;
+ int SavedY;
+ int SavedWidth;
+ int SavedHeight;
+
+ int SavedRootWidth;
+ int SavedRootHeight;
+
+ /*
+ * Set if agent is running nested in another
+ * agent X server.
+ */
+
+ int Nested;
+
+ /*
+ * Selected backing-store mode.
+ */
+
+ BackingStoreMode BackingStore;
+
+ /*
+ * Selected clipboard mode.
+ */
+
+ ClipboardMode Clipboard;
+
+ /*
+ * Enable agent to use the MITSHM extension in
+ * path from remote proxy to the real X server.
+ */
+
+ int SharedMemory;
+
+ /*
+ * Enable agent to use shared Pixmaps
+ */
+
+ int SharedPixmaps;
+
+ /*
+ * Enable agent to propagate keyboard and pointer
+ * device configuration to the remote X server.
+ */
+
+ int DeviceControl;
+
+ /*
+ * Explicitly asked config propagation.
+ */
+
+ int DeviceControlUserDefined;
+
+ /*
+ * Resuming keyboard device corrects keymap if session
+ * migrates across platforms with different keycode
+ * layout.
+ */
+
+ int ResetKeyboardAtResume;
+
+ /*
+ * Reset server when the last client disconnects.
+ */
+
+ int Reset;
+
+ /*
+ * Geometry of the agent root window, relative to
+ * the agent default window.
+ */
+
+ int RootX;
+ int RootY;
+ int RootWidth;
+ int RootHeight;
+
+ /*
+ * Horizontal and vertical span of the
+ * agent viewport.
+ */
+
+ int ViewportXSpan;
+ int ViewportYSpan;
+
+ /*
+ * True if the user can resize the desktop
+ * by dragging the window border.
+ */
+
+ int DesktopResize;
+
+ /*
+ * The scaling ratio of the shadow agent.
+ */
+
+ int Ratio;
+
+ int XRatio;
+
+ int YRatio;
+
+ float FloatRatio;
+
+ float FloatXRatio;
+
+ float FloatYRatio;
+
+ /*
+ * The shadow agent uses the Damage extension.
+ */
+
+ int UseDamage;
+
+ /*
+ * Was the agent run with the -B option?
+ */
+
+ int Binder;
+
+ char *BinderOptions;
+
+ /*
+ * Set if the agent has to connect to a
+ * desktop manager to start the session.
+ */
+
+ int Xdmcp;
+
+ /*
+ * Latency of the link. It is simply set
+ * to a reference value, calculated based
+ * on the time required to complete the
+ * query of the agent's atoms at session
+ * startup.
+ */
+
+ int DisplayLatency;
+
+ /*
+ * Size of the Xlib display buffer. The
+ * default is set according to the link
+ * type.
+ */
+
+ int DisplayBuffer;
+
+ /*
+ * Buffer coalescence timeout.
+ */
+
+ int DisplayCoalescence;
+
+ /*
+ * Use the composite extension when
+ * available on the remote display.
+ */
+
+ int Composite;
+
+ /*
+ * If set, don't skip internal operations
+ * when the agent window is not fully visible.
+ */
+
+ int IgnoreVisibility;
+
+ /*
+ * If set, prevent the shadow session to
+ * interact with master diplay.
+ */
+
+ int ViewOnly;
+
+ /*
+ * If true select a lossy or lossless comp-
+ * ression method based on the characterist-
+ * ics of the image.
+ */
+
+ int Adaptive;
+
+ /*
+ * Stream the images and update the display
+ * when the image has been completely trans-
+ * ferred.
+ */
+
+ int Streaming;
+
+ /*
+ * Use a lazy approach in updating the remote
+ * display. This means delaying the bandwidth
+ * consuming graphic operations and synchroniz-
+ * ing the screen at idle time.
+ */
+
+ int DeferLevel;
+
+ /*
+ * Maxuimum elapsed time before a new full
+ * synchronization.
+ */
+
+ unsigned long DeferTimeout;
+
+ /*
+ * Maximum size of the tile used when sending
+ * an image to the remote display.
+ */
+
+ int TileWidth;
+ int TileHeight;
+
+ /*
+ * Enabling/disabling the pulldown menu.
+ */
+
+ int Menu;
+
+ /*
+ * Specify the Operative System of the client.
+ */
+
+ int ClientOs;
+
+ /*
+ * Inhibit some XKEYBOARD requests.
+ */
+
+ int InhibitXkb;
+
+ /*
+ * Maximum number of bytes that can be pasted from
+ * an NX session into an external application.
+ */
+
+ int CopyBufferSize;
+
+ /*
+ * Max image data rate to the encoder input.
+ */
+
+ int ImageRateLimit;
+
+ /*
+ * True if agent should not exit if there are no
+ * clients in rootless mode
+ */
+
+ int NoRootlessExit;
+
+ /*
+ * Store if the user wants Xinerama. There are variables called
+ * noPanoramiXExtension and noRRXineramaExtensison in os/utils.c but
+ * we cannot rely on them because RandR and PanoramiX change their
+ * values when trying to initialize. So we use this variable to
+ * save the user preference provided by the -/+(rr)xinerama parameter(s)
+ * before initalizing those extensions.
+ */
+
+ int Xinerama;
+
+ /*
+ * Sleep delay in microseconds.
+ */
+
+ unsigned int SleepTime;
+
+ /*
+ * Tolerance - tightens or loosens reconnect checks.
+ */
+
+ ToleranceChecksMode ReconnectTolerance;
+
+} AgentOptionsRec;
+
+typedef AgentOptionsRec *AgentOptionsPtr;
+
+extern AgentOptionsPtr nxagentOptionsPtr;
+
+/*
+ * Macros and functions giving access to options.
+ */
+
+#define nxagentOption(option) \
+ (nxagentOptionsPtr -> option)
+
+#define nxagentChangeOption(option, value) \
+ (nxagentOptionsPtr -> option = (value))
+
+#define nxagentOptions() \
+ (nxagentOptionsPtr)
+
+/*
+ * Initialize the options to the default values.
+ */
+
+extern void nxagentInitOptions(void);
+
+/*
+ * Initialize some options to the default values
+ * at reconnection.
+ */
+
+extern void nxagentResetOptions(void);
+
+/*
+ * Save a copy of the current option repository.
+ */
+
+extern void nxagentSaveOptions(void);
+
+/*
+ * Restore the options reset by nxagentResetOptions
+ * to their backup value.
+ */
+
+extern void nxagentRestoreOptions(void);
+
+#endif /* __Options_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixels.c b/nx-X11/programs/Xserver/hw/nxagent/Pixels.c
new file mode 100644
index 000000000..e59ef97ab
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.c
@@ -0,0 +1,392 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Xmd.h"
+#include "Xlib.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define PIXEL_ELEMENTS 256
+#define PIXEL_THRESHOLD 8
+#define PIXEL_STEP 7
+
+unsigned int Get16(const char *buffer, int order);
+unsigned int Get24(const char *buffer, int order);
+unsigned int Get32(const char *buffer, int order);
+
+void Put16(unsigned int value, char *buffer, int order);
+void Put24(unsigned int value, char *buffer, int order);
+void Put32(unsigned int value, char *buffer, int order);
+
+static int nxagentComparePixels(const void *p1, const void *p2)
+{
+ int pixel1 = *((int *) p1);
+ int pixel2 = *((int *) p2);
+
+ return (pixel1 < pixel2 ? -1 : (pixel1 == pixel2 ? 0 : 1));
+}
+
+int nxagentUniquePixels(XImage *image)
+{
+ int i = 0;
+
+ int pixels[PIXEL_ELEMENTS];
+
+ int elements = PIXEL_ELEMENTS;
+ int unique = 0;
+
+ int total;
+ int ratio;
+ int step;
+
+ int last = -1;
+
+ const char *next = image -> data;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Image geometry [%d,%d] depth [%d] bits per pixel [%d].\n",
+ image -> width, image -> height, image -> depth, image -> bits_per_pixel);
+ #endif
+
+ /*
+ * Take at most 256 pixels from the image.
+ */
+
+ total = image -> width * image -> height;
+
+ step = total / elements;
+
+ if (step < PIXEL_STEP)
+ {
+ step = PIXEL_STEP;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Step is [%d] with [%d] pixels and [%d] elements.\n",
+ step, total, elements);
+ #endif
+
+ /*
+ * Shift at the left after each scanline.
+ */
+
+ if (image -> bytes_per_line % step == 0)
+ {
+ step++;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Increasing step to [%d] with [%d] bytes per line.\n",
+ step, image -> bytes_per_line);
+ #endif
+ }
+
+ elements = total / step;
+
+ if (elements > PIXEL_ELEMENTS)
+ {
+ elements = PIXEL_ELEMENTS;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Step is now [%d] with [%d] elements.\n",
+ step, elements);
+ #endif
+
+ if (elements < PIXEL_THRESHOLD)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Assuming ratio [100] with only [%d] elements.\n",
+ elements);
+ #endif
+
+ return 100;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Scanning [%d] pixels out of [%d] with step [%d].\n",
+ elements, total, step);
+ #endif
+
+ /*
+ * Take one pixel every n from the image and
+ * add it to the array.
+ */
+
+ switch (image -> bits_per_pixel)
+ {
+ case 32:
+ {
+ for (i = 0; i < elements; i++)
+ {
+ pixels[i] = Get32(next, image -> byte_order);
+
+ next += (4 * step);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n",
+ i, pixels[i]);
+ #endif
+ }
+
+ break;
+ }
+ case 24:
+ {
+ for (i = 0; i < elements; i++)
+ {
+ pixels[i] = Get24(next, image -> byte_order);
+
+ next += (3 * step);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n",
+ i, pixels[i]);
+ #endif
+ }
+
+ break;
+ }
+ case 16:
+ case 15:
+ {
+ /*
+ * Note that the padding bytes at the end
+ * of the scanline are included in the set.
+ * This is not a big problem. What we want
+ * to find out is just how compressible is
+ * the image data.
+ */
+
+ for (i = 0; i < elements; i++)
+ {
+ pixels[i] = Get16(next, image -> byte_order);
+
+ next += (2 * step);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n",
+ i, pixels[i]);
+ #endif
+ }
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentUniquePixels: PANIC! Assuming ratio [100] with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ return 100;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Sorting [%d] elements in the list.\n", i);
+ #endif
+
+ qsort(pixels, elements, sizeof(int), nxagentComparePixels);
+
+ for (i = 0; i < elements; i++)
+ {
+ if (last != pixels[i])
+ {
+ unique++;
+
+ last = pixels[i];
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentUniquePixels: pixels[%d][0x%08x].\n",
+ i, pixels[i]);
+ #endif
+ }
+
+ ratio = unique * 100 / elements;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentUniquePixels: Found [%d] unique pixels out of [%d] with ratio [%d%%].\n",
+ unique, elements, ratio);
+ #endif
+
+ return ratio;
+}
+
+unsigned int Get16(const char *buffer, int order)
+{
+ unsigned int result;
+
+ if (order == MSBFirst)
+ {
+ result = *buffer;
+
+ result <<= 8;
+
+ result += buffer[1];
+ }
+ else
+ {
+ result = buffer[1];
+
+ result <<= 8;
+
+ result += *buffer;
+ }
+
+ return result;
+}
+
+unsigned int Get24(const char *buffer, int order)
+{
+ int i;
+
+ const char *next = (order == MSBFirst ? buffer : buffer + 2);
+
+ unsigned int result = 0;
+
+ for (i = 0; i < 3; i++)
+ {
+ result <<= 8;
+
+ result += *next;
+
+ if (order == MSBFirst)
+ {
+ next++;
+ }
+ else
+ {
+ next--;
+ }
+ }
+
+ return result;
+}
+
+unsigned int Get32(const char *buffer, int order)
+{
+ int i;
+
+ const char *next = (order == MSBFirst ? buffer : buffer + 3);
+
+ unsigned int result = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ result <<= 8;
+
+ result += *next;
+
+ if (order == MSBFirst)
+ {
+ next++;
+ }
+ else
+ {
+ next--;
+ }
+ }
+
+ return result;
+}
+
+void Put16(unsigned int value, char *buffer, int order)
+{
+ if (order == MSBFirst)
+ {
+ buffer[1] = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+
+ *buffer = (unsigned char) value;
+ }
+ else
+ {
+ *buffer = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+
+ buffer[1] = (unsigned char) value;
+ }
+}
+
+void Put24(unsigned int value, char *buffer, int order)
+{
+ int i;
+
+ if (order == MSBFirst)
+ {
+ buffer += 2;
+
+ for (i = 3; i > 0; i--)
+ {
+ *buffer-- = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+ }
+ }
+ else
+ {
+ for (i = 3; i > 0; i--)
+ {
+ *buffer++ = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+ }
+ }
+}
+
+void Put32(unsigned int value, char *buffer, int order)
+{
+ int i;
+
+ if (order == MSBFirst)
+ {
+ buffer += 3;
+
+ for (i = 4; i > 0; i--)
+ {
+ *buffer-- = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+ }
+ }
+ else
+ {
+ for (i = 4; i > 0; i--)
+ {
+ *buffer++ = (unsigned char) (value & 0xff);
+
+ value >>= 8;
+ }
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixels.h b/nx-X11/programs/Xserver/hw/nxagent/Pixels.h
new file mode 100644
index 000000000..fa25a46c7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixels.h
@@ -0,0 +1,188 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Pixels_H__
+#define __Pixels_H__
+
+#include "Visual.h"
+#include "Drawable.h"
+#include "Composite.h"
+
+/*
+ * Count how many pixels are different
+ * in the image.
+ */
+
+int nxagentUniquePixels(XImage *image);
+
+/*
+ * Convert a 32 bit pixel to 16 bit.
+ */
+
+#define Color32to16(color) \
+do \
+{ \
+ Visual *pVisual; \
+\
+ pVisual = nxagentDefaultVisual(nxagentDefaultScreen); \
+\
+ if (pVisual -> green_mask == 0x7e0) \
+ { \
+ /* \
+ * bit mask 5-6-5 \
+ */ \
+\
+ color = (((color & (pVisual -> blue_mask << 3)) >> 3) | \
+ ((color & (pVisual -> green_mask << 5)) >> 5) | \
+ ((color & (pVisual -> red_mask << 8)) >> 8)); \
+ } \
+ else \
+ { \
+ /* \
+ * bit mask 5-5-5 \
+ */ \
+\
+ color = (((color & (pVisual -> blue_mask << 3)) >> 3) | \
+ ((color & (pVisual -> green_mask << 6)) >> 6) | \
+ ((color & (pVisual -> red_mask << 9)) >> 9)); \
+ } \
+} \
+while (0)
+
+/*
+ * Rules to break the synchronization loop.
+ */
+
+#define breakOnBlocking(mask) \
+ (((mask) != NEVER_BREAK) && ((mask) & BLOCKING_BREAK) && \
+ nxagentBlocking == 1)
+
+#define breakOnCongestion(mask) \
+ (((mask) != NEVER_BREAK) && ((mask) & CONGESTION_BREAK) && \
+ nxagentCongestion > 4)
+
+#define breakOnBlockingOrCongestion(mask) \
+ (breakOnBlocking(mask) != 0 || breakOnCongestion(mask) != 0)
+
+#define breakOnCongestionDrawable(mask, pDrawable) \
+ (((mask) != NEVER_BREAK) && ((mask) & CONGESTION_BREAK) && \
+ (nxagentCongestion > 4 || \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP && \
+ nxagentCongestion > 1)))
+
+#define breakOnEvent(mask) \
+ (((mask) != NEVER_BREAK) && ((mask) & EVENT_BREAK) && \
+ nxagentUserInput(NULL) == 1)
+
+#define canBreakOnTimeout(mask) \
+ (((mask) != NEVER_BREAK) && nxagentOption(Shadow) == 0)
+
+/*
+ * Macros defining the conditions to
+ * defer X requests.
+ */
+
+#define NXAGENT_SHOULD_DEFER_TRAPEZOIDS(pDrawable) \
+ (nxagentOption(DeferLevel) >= 2 && \
+ nxagentDrawableContainGlyphs(pDrawable) == 0 && \
+ nxagentOption(LinkType) < LINK_TYPE_ADSL && \
+ nxagentCongestion > 4)
+
+/*
+FIXME: The condition checking for the render
+ version is a workaround implemented to
+ avoid problems with the render composi-
+ te on XFree86 remote server.
+*/
+/*
+FIXME: Changed macro: NXAGENT_SHOULD_DEFER_COMPOSITE
+ to handle situation, when pSrc -> pDrawable
+ is NULL. This case happens with gradients
+ and solid fill.
+
+#define NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst) \
+ ((nxagentRenderVersionMajor == 0 && \
+ nxagentRenderVersionMinor == 8 && \
+ (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP) || \
+ ((pDst) -> pDrawable -> type == DRAWABLE_PIXMAP && \
+ (nxagentDrawableStatus((pSrc) -> pDrawable) == NotSynchronized || \
+ ((pMask) && nxagentDrawableStatus((pMask) -> pDrawable) == NotSynchronized)) && \
+ nxagentOption(DeferLevel) == 1) || \
+ (nxagentOption(DeferLevel) >= 2 && \
+ nxagentOption(LinkType) < LINK_TYPE_ADSL))
+*/
+#define NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst) \
+ ((nxagentRenderVersionMajor == 0 && \
+ nxagentRenderVersionMinor == 8 && \
+ (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP) || \
+ (nxagentOption(DeferLevel) >= 2 && \
+ nxagentOption(LinkType) < LINK_TYPE_ADSL) || \
+ (nxagentOption(DeferLevel) == 1 && \
+ (pDst) -> pDrawable -> type == DRAWABLE_PIXMAP && \
+ (((pSrc) -> pDrawable && nxagentDrawableStatus((pSrc) -> pDrawable) == NotSynchronized) || \
+ ((pMask) && (pMask) -> pDrawable && nxagentDrawableStatus((pMask) -> pDrawable) == NotSynchronized))))
+
+
+#define NXAGENT_SHOULD_DEFER_PUTIMAGE(pDrawable) \
+ (nxagentSplitTrap == 0 && \
+ nxagentOption(DeferLevel) > 0)
+
+/*
+ * Macros defining the conditions to
+ * start the synchronization loops of
+ * resources.
+ */
+
+#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_WINDOWS(mask) \
+ ((nxagentCorruptedWindows > 0 && breakOnBlockingOrCongestion(mask) == 0) || \
+ mask == NEVER_BREAK)
+
+#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_BACKGROUNDS(mask) \
+ ((nxagentCorruptedWindows == 0 && nxagentCorruptedBackgrounds > 0 && \
+ breakOnBlockingOrCongestion(mask) == 0) || mask == NEVER_BREAK)
+
+#define NXAGENT_SHOULD_SYNCHRONIZE_CORRUPTED_PIXMAPS(mask) \
+ ((nxagentCorruptedWindows == 0 && nxagentCorruptedPixmaps > 0 && \
+ nxagentCongestion == 0 && nxagentBlocking == 0) || \
+ mask == NEVER_BREAK)
+
+/*
+ * Macros defining the conditions to
+ * synchronize a single resource.
+ */
+
+#define NXAGENT_SHOULD_SYNCHRONIZE_WINDOW(pDrawable) \
+ (nxagentWindowIsVisible((WindowPtr) pDrawable) == 1 && \
+ (nxagentDefaultWindowIsVisible() == 1 || nxagentCompositeEnable == 1))
+
+#define MINIMUM_PIXMAP_USAGE_COUNTER 2
+
+#define NXAGENT_SHOULD_SYNCHRONIZE_PIXMAP(pDrawable) \
+ (nxagentPixmapUsageCounter((PixmapPtr) pDrawable) >= \
+ MINIMUM_PIXMAP_USAGE_COUNTER || \
+ nxagentIsCorruptedBackground((PixmapPtr) pDrawable) == 1)
+
+#endif /* __Pixels_H__ */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c b/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c
new file mode 100644
index 000000000..be5408d13
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmap.c
@@ -0,0 +1,1660 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "scrnintstr.h"
+#include "miscstruct.h"
+#include "pixmapstr.h"
+#include "dixstruct.h"
+#include "regionstr.h"
+#include "../../include/gc.h"
+#include "servermd.h"
+#include "mi.h"
+
+#include "../../fb/fb.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Pixmaps.h"
+#include "Trap.h"
+#include "GCs.h"
+#include "GCOps.h"
+#include "Image.h"
+#include "Split.h"
+#include "Drawable.h"
+#include "Visual.h"
+#include "Client.h"
+#include "Events.h"
+#include "Holder.h"
+#include "Args.h"
+
+#include "compext/Compext.h"
+#include <nx/NXpack.h>
+
+RESTYPE RT_NX_PIXMAP;
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+#ifdef TEST
+#include "Font.h"
+#endif
+
+int nxagentPixmapPrivateIndex;
+
+int nxagentCorruptedPixmaps;
+int nxagentCorruptedBackgrounds;
+
+/*
+ * Force deallocation of the virtual pixmap.
+ */
+
+static Bool nxagentDestroyVirtualPixmap(PixmapPtr pPixmap);
+
+/*
+ * This serves as a tool to check the synchronization
+ * between pixmaps in framebuffer and the correspondent
+ * pixmaps in the real X server.
+ */
+
+#ifdef TEST
+Bool nxagentCheckPixmapIntegrity(PixmapPtr pPixmap);
+#endif
+
+struct nxagentPixmapPair
+{
+ Pixmap pixmap;
+ PixmapPtr pMap;
+};
+
+PixmapPtr nxagentCreatePixmap(ScreenPtr pScreen, int width, int height,
+ int depth, unsigned usage_hint)
+{
+ nxagentPrivPixmapPtr pPixmapPriv, pVirtualPriv;
+
+ PixmapPtr pPixmap;
+ PixmapPtr pVirtual;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreatePixmap: Creating pixmap with width [%d] "
+ "height [%d] depth [%d] and allocation hint [%d].\n",
+ width, height, depth, usage_hint);
+ #endif
+
+ /*
+ * Create the pixmap structure but do
+ * not allocate memory for the data.
+ */
+
+ pPixmap = AllocatePixmap(pScreen, 0);
+
+ if (!pPixmap)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCreatePixmap: WARNING! Failed to create pixmap with "
+ "width [%d] height [%d] depth [%d] and allocation hint [%d].\n",
+ width, height, depth, usage_hint);
+ #endif
+
+ return NullPixmap;
+ }
+
+ /*
+ * Initialize the core members.
+ */
+
+ pPixmap -> drawable.type = DRAWABLE_PIXMAP;
+ pPixmap -> drawable.class = 0;
+ pPixmap -> drawable.pScreen = pScreen;
+ pPixmap -> drawable.depth = depth;
+ pPixmap -> drawable.bitsPerPixel = BitsPerPixel(depth);
+ pPixmap -> drawable.id = 0;
+ pPixmap -> drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pPixmap -> drawable.x = 0;
+ pPixmap -> drawable.y = 0;
+ pPixmap -> drawable.width = width;
+ pPixmap -> drawable.height = height;
+ pPixmap -> devKind = 0;
+ pPixmap -> refcnt = 1;
+ pPixmap -> devPrivate.ptr = NULL;
+ pPixmap -> usage_hint = usage_hint;
+
+ /*
+ * Initialize the privates of the real picture.
+ */
+
+ pPixmapPriv = nxagentPixmapPriv(pPixmap);
+
+ pPixmapPriv -> isVirtual = False;
+ pPixmapPriv -> isShared = nxagentShmPixmapTrap;
+
+ /*
+ * The shared memory pixmaps are never
+ * synchronized with the remote X Server.
+ */
+
+ if (pPixmapPriv -> isShared == 1)
+ {
+ BoxRec box;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = width;
+ box.y2 = height;
+
+ pPixmapPriv -> corruptedRegion = RegionCreate(&box, 1);
+ }
+ else
+ {
+ pPixmapPriv -> corruptedRegion = RegionCreate((BoxRec *) NULL, 1);
+ }
+
+ pPixmapPriv -> corruptedBackground = 0;
+
+ pPixmapPriv -> containGlyphs = 0;
+ pPixmapPriv -> containTrapezoids = 0;
+
+ /*
+ * The lazy encoding policy generally does
+ * not send on remote X server the off-screen
+ * images, by preferring to synchronize the
+ * windows content. Anyway this behaviour may
+ * be inadvisable if a pixmap is used, for
+ * example, for multiple copy areas on screen.
+ * This counter serves the purpose, taking in-
+ * to account the number of times the pixmap
+ * has been used as source for a deferred
+ * operation.
+ */
+
+ pPixmapPriv -> usageCounter = 0;
+
+ pPixmapPriv -> corruptedBackgroundId = 0;
+ pPixmapPriv -> corruptedId = 0;
+
+ pPixmapPriv -> synchronizationBitmap = NullPixmap;
+
+ pPixmapPriv -> corruptedTimestamp = 0;
+
+ pPixmapPriv -> splitResource = NULL;
+
+ pPixmapPriv -> isBackingPixmap = 0;
+
+ /*
+ * Create the pixmap based on the default
+ * windows. The proxy knows this and uses
+ * this information to optimize encode the
+ * create pixmap message by including the
+ * id of the drawable in the checksum.
+ */
+
+ if (width != 0 && height != 0 && nxagentGCTrap == 0)
+ {
+ pPixmapPriv -> id = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pScreen -> myNum],
+ width, height, depth);
+ }
+ else
+ {
+ pPixmapPriv -> id = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreatePixmap: Skipping the creation of pixmap at [%p] on real "
+ "X server with nxagentGCTrap [%d].\n", (void *) pPixmap, nxagentGCTrap);
+ #endif
+ }
+
+ pPixmapPriv -> mid = FakeClientID(serverClient -> index);
+
+ AddResource(pPixmapPriv -> mid, RT_NX_PIXMAP, pPixmap);
+
+ pPixmapPriv -> pRealPixmap = pPixmap;
+ pPixmapPriv -> pVirtualPixmap = NULL;
+ pPixmapPriv -> pPicture = NULL;
+
+ /*
+ * Create the pixmap in the virtual framebuffer.
+ */
+
+ pVirtual = fbCreatePixmap(pScreen, width, height, depth, usage_hint);
+
+ if (pVirtual == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCreatePixmap: PANIC! Failed to create virtual pixmap with "
+ "width [%d] height [%d] depth [%d] and allocation hint [%d].\n",
+ width, height, depth, usage_hint);
+ #endif
+
+ nxagentDestroyPixmap(pPixmap);
+
+ return NullPixmap;
+ }
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentCreatePixmap: Allocated memory for the Virtual %sPixmap %p of real Pixmap %p (%dx%d),",
+ "allocation hint [%d].\n",
+ nxagentShmPixmapTrap ? "Shm " : "", (void *) pVirtual, (void *) pPixmap, width, height, usage_hint);
+ #endif
+
+ pPixmapPriv -> pVirtualPixmap = pVirtual;
+
+ /*
+ * Initialize the privates of the virtual picture. We
+ * could avoid to use a flag and just check the pointer
+ * to the virtual pixmap that, if the pixmap is actually
+ * virtual, will be NULL. Unfortunately the flag can be
+ * changed in nxagentValidateGC(). That code should be
+ * removed in future.
+ */
+
+ pVirtualPriv = nxagentPixmapPriv(pVirtual);
+
+ pVirtualPriv -> isVirtual = True;
+ pVirtualPriv -> isShared = nxagentShmPixmapTrap;
+
+ pVirtualPriv -> corruptedRegion = RegionCreate((BoxRec *) NULL, 1);
+
+ pVirtualPriv -> corruptedBackground = 0;
+
+ pVirtualPriv -> containGlyphs = 0;
+ pVirtualPriv -> containTrapezoids = 0;
+
+ pVirtualPriv -> usageCounter = 0;
+
+ pVirtualPriv -> corruptedBackgroundId = 0;
+ pVirtualPriv -> corruptedId = 0;
+
+ pVirtualPriv -> synchronizationBitmap = NullPixmap;
+
+ pVirtualPriv -> corruptedTimestamp = 0;
+
+ pVirtualPriv -> splitResource = NULL;
+
+ /*
+ * We might distinguish real and virtual pixmaps by
+ * checking the pointers to pVirtualPixmap. We should
+ * also remove the copy of id and use the one of the
+ * real pixmap.
+ */
+
+ pVirtualPriv -> id = pPixmapPriv -> id;
+ pVirtualPriv -> mid = 0;
+
+ /*
+ * Storing a pointer back to the real pixmap is
+ * silly. Unfortunately this is the way it has
+ * been originally implemented. See also the
+ * comment in destroy of the pixmap.
+ */
+
+ pVirtualPriv -> pRealPixmap = pPixmap;
+ pVirtualPriv -> pVirtualPixmap = NULL;
+ pVirtualPriv -> pPicture = NULL;
+
+ /*
+ * Check that the virtual pixmap is created with
+ * the appropriate bits-per-plane, otherwise free
+ * everything and return.
+ */
+
+ if (pVirtual -> drawable.bitsPerPixel == 0)
+ {
+ #ifdef WARNING
+
+ fprintf(stderr, "nxagentCreatePixmap: WARNING! Virtual pixmap at [%p] has invalid "
+ "bits per pixel.\n", (void *) pVirtual);
+
+ fprintf(stderr, "nxagentCreatePixmap: WARNING! Real pixmap created with width [%d] "
+ "height [%d] depth [%d] bits per pixel [%d] and allocation hint [%d].\n",
+ pPixmap -> drawable.width,
+ pPixmap -> drawable.height = height, pPixmap -> drawable.depth,
+ pPixmap -> drawable.bitsPerPixel,
+ usage_hint);
+ #endif
+
+ if (!nxagentRenderTrap)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Disabling render extension due to missing pixmap format.\n");
+ #endif
+
+ nxagentRenderTrap = 1;
+ }
+
+ nxagentDestroyPixmap(pPixmap);
+
+ return NullPixmap;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreatePixmap: Created pixmap at [%p] virtual at [%p] with width [%d] "
+ "height [%d] depth [%d] and allocation hint [%d].\n",
+ (void *) pPixmap, (void *) pVirtual, width, height, depth, usage_hint);
+ #endif
+
+ return pPixmap;
+}
+
+Bool nxagentDestroyPixmap(PixmapPtr pPixmap)
+{
+ PixmapPtr pVirtual;
+
+ nxagentPrivPixmapPtr pPixmapPriv;
+
+ if (!pPixmap)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentDestroyPixmap: PANIC! Invalid attempt to destroy "
+ "a null pixmap pointer.\n");
+ #endif
+
+ return False;
+ }
+
+ pPixmapPriv = nxagentPixmapPriv(pPixmap);
+
+ pVirtual = pPixmapPriv -> pVirtualPixmap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPixmap: Destroying pixmap at [%p] with virtual at [%p].\n",
+ (void *) pPixmap, (void *) pVirtual);
+ #endif
+
+ if (pPixmapPriv -> isVirtual)
+ {
+ int refcnt;
+
+ /*
+ * For some pixmaps we receive the destroy only for the
+ * virtual. Infact to draw in the framebuffer we can use
+ * the virtual pixmap instead of the pointer to the real
+ * one. As the virtual pixmap can collect references, we
+ * must transfer those references to the real pixmap so
+ * we can continue as the destroy had been requested for
+ * it.
+ */
+
+ pVirtual = pPixmap;
+ pPixmap = pPixmapPriv -> pRealPixmap;
+
+ pPixmapPriv = nxagentPixmapPriv(pPixmap);
+
+ /*
+ * Move the references accumulated by the virtual
+ * pixmap into the references of the real one.
+ */
+
+ refcnt = pVirtual -> refcnt - 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPixmap: Adding [%d] references to pixmap at [%p].\n",
+ refcnt, (void *) pPixmap);
+ #endif
+
+ pPixmap -> refcnt += refcnt;
+
+ pVirtual -> refcnt -= refcnt;
+ }
+
+ --pPixmap -> refcnt;
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentDestroyPixmap: Pixmap has now [%d] references with virtual pixmap [%d].\n",
+ pPixmap -> refcnt, pVirtual -> refcnt);
+
+ if (pVirtual != NULL && pVirtual -> refcnt != 1)
+ {
+ fprintf(stderr, "nxagentDestroyPixmap: PANIC! Virtual pixmap has [%d] references.\n",
+ pVirtual -> refcnt);
+ }
+
+ #endif
+
+ if (pPixmap -> refcnt > 0)
+ {
+ return True;
+ }
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentDestroyPixmap: Managing to destroy the pixmap at [%p]\n",
+ (void *) pPixmap);
+ #endif
+
+ nxagentRemoveItemBSPixmapList(nxagentPixmap(pPixmap));
+
+ nxagentDestroyVirtualPixmap(pPixmap);
+
+ if (pPixmapPriv -> corruptedRegion != NullRegion)
+ {
+ RegionDestroy(pPixmapPriv -> corruptedRegion);
+
+ pPixmapPriv -> corruptedRegion = NullRegion;
+ }
+
+ if (nxagentSynchronization.pDrawable == (DrawablePtr) pPixmap)
+ {
+ nxagentSynchronization.pDrawable = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPixmap: Synchronization drawable [%p] removed from resources.\n",
+ (void *) pPixmap);
+ #endif
+ }
+
+ nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND);
+
+ nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP);
+
+ nxagentDestroyDrawableBitmap((DrawablePtr) pPixmap);
+
+ if (pPixmapPriv -> splitResource != NULL)
+ {
+ nxagentReleaseSplit((DrawablePtr) pPixmap);
+ }
+
+ /*
+ * A pixmap with width and height set to 0 is
+ * created at the beginning. To this pixmap is
+ * not assigned an id. This is likely a scratch
+ * pixmap used by the X server.
+ */
+
+ if (pPixmapPriv -> id)
+ {
+ XFreePixmap(nxagentDisplay, pPixmapPriv -> id);
+ }
+
+ if (pPixmapPriv -> mid)
+ {
+ FreeResource(pPixmapPriv -> mid, RT_NONE);
+ }
+
+ free(pPixmap);
+
+ return True;
+}
+
+Bool nxagentDestroyVirtualPixmap(PixmapPtr pPixmap)
+{
+ PixmapPtr pVirtual;
+ nxagentPrivPixmapPtr pVirtualPriv;
+
+ pVirtual = nxagentPixmapPriv(pPixmap) -> pVirtualPixmap;
+
+ /*
+ * Force the routine to get rid of the virtual
+ * pixmap.
+ */
+
+ if (pVirtual != NULL)
+ {
+ pVirtual -> refcnt = 1;
+
+ pVirtualPriv = nxagentPixmapPriv(pVirtual);
+
+ if (pVirtualPriv -> corruptedRegion != NullRegion)
+ {
+ RegionDestroy(pVirtualPriv -> corruptedRegion);
+
+ pVirtualPriv -> corruptedRegion = NullRegion;
+ }
+
+ fbDestroyPixmap(pVirtual);
+ }
+
+ return True;
+}
+
+RegionPtr nxagentPixmapToRegion(PixmapPtr pPixmap)
+{
+ #ifdef TEST
+ fprintf(stderr, "PixmapToRegion: Pixmap = [%p] nxagentVirtualPixmap = [%p]\n",
+ (void *) pPixmap, (void *) nxagentVirtualPixmap(pPixmap));
+ #endif
+
+ return fbPixmapToRegion(nxagentVirtualPixmap(pPixmap));
+}
+
+Bool nxagentModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, void * pPixData)
+{
+ PixmapPtr pVirtualPixmap;
+
+ /*
+ * See miModifyPixmapHeader() in miscrinit.c. This
+ * function is used to recycle the scratch pixmap
+ * for this screen. We let it refer to the virtual
+ * pixmap.
+ */
+
+ if (!pPixmap)
+ {
+ return False;
+ }
+
+ if (nxagentPixmapIsVirtual(pPixmap))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentModifyPixmapHeader: PANIC! Pixmap at [%p] is virtual.\n",
+ (void *) pPixmap);
+ #endif
+
+ FatalError("nxagentModifyPixmapHeader: PANIC! Pixmap is virtual.");
+ }
+
+ pVirtualPixmap = nxagentVirtualPixmap(pPixmap);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentModifyPixmapHeader: Pixmap at [%p] Virtual at [%p].\n",
+ (void *) pPixmap, (void *) pVirtualPixmap);
+
+ fprintf(stderr, "nxagentModifyPixmapHeader: Pixmap has width [%d] height [%d] depth [%d] "
+ "bits-per-pixel [%d] devKind [%d] pPixData [%p].\n", pPixmap->drawable.width,
+ pPixmap->drawable.height, pPixmap->drawable.depth, pPixmap->drawable.bitsPerPixel,
+ pPixmap->devKind, (void *) pPixmap->devPrivate.ptr);
+
+ fprintf(stderr, "nxagentModifyPixmapHeader: New parameters are width [%d] height [%d] depth [%d] "
+ "bits-per-pixel [%d] devKind [%d] pPixData [%p].\n", width, height, depth,
+ bitsPerPixel, devKind, (void *) pPixData);
+ #endif
+
+ if ((width > 0) && (height > 0) && (depth > 0) &&
+ (bitsPerPixel > 0) && (devKind > 0) && pPixData)
+ {
+ pPixmap->drawable.depth = depth;
+ pPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ pPixmap->drawable.id = 0;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pPixmap->drawable.x = 0;
+ pPixmap->drawable.y = 0;
+ pPixmap->drawable.width = width;
+ pPixmap->drawable.height = height;
+ pPixmap->devKind = devKind;
+ pPixmap->refcnt = 1;
+ pPixmap->devPrivate.ptr = pPixData;
+
+ pVirtualPixmap->drawable.depth = depth;
+ pVirtualPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ pVirtualPixmap->drawable.id = 0;
+ pVirtualPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pVirtualPixmap->drawable.x = 0;
+ pVirtualPixmap->drawable.y = 0;
+ pVirtualPixmap->drawable.width = width;
+ pVirtualPixmap->drawable.height = height;
+ pVirtualPixmap->devKind = devKind;
+ pVirtualPixmap->refcnt = 1;
+ pVirtualPixmap->devPrivate.ptr = pPixData;
+ }
+ else
+ {
+ if (width > 0)
+ pPixmap->drawable.width = width;
+
+ if (height > 0)
+ pPixmap->drawable.height = height;
+
+ if (depth > 0)
+ pPixmap->drawable.depth = depth;
+
+ if (bitsPerPixel > 0)
+ pPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ else if ((bitsPerPixel < 0) && (depth > 0))
+ pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
+
+ if (devKind > 0)
+ pPixmap->devKind = devKind;
+ else if ((devKind < 0) && ((width > 0) || (depth > 0)))
+ pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width,
+ pPixmap->drawable.depth);
+
+ if (pPixData)
+ pPixmap->devPrivate.ptr = pPixData;
+
+ /*
+ * XXX This was the previous assignment:
+ *
+ * pVirtualPixmap->devPrivate.ptr = pPixData;
+ */
+
+ if (width > 0)
+ pVirtualPixmap->drawable.width = width;
+
+ if (height > 0)
+ pVirtualPixmap->drawable.height = height;
+
+ if (depth > 0)
+ pVirtualPixmap->drawable.depth = depth;
+
+ if (bitsPerPixel > 0)
+ pVirtualPixmap->drawable.bitsPerPixel = bitsPerPixel;
+ else if ((bitsPerPixel < 0) && (depth > 0))
+ pVirtualPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
+
+ if (devKind > 0)
+ pVirtualPixmap->devKind = devKind;
+ else if ((devKind < 0) && ((width > 0) || (depth > 0)))
+ pVirtualPixmap->devKind = PixmapBytePad(pVirtualPixmap->drawable.width,
+ pVirtualPixmap->drawable.depth);
+
+ if (pPixData)
+ pVirtualPixmap->devPrivate.ptr = pPixData;
+
+ #ifdef PANIC
+
+ if (pPixmap->drawable.x != 0 || pPixmap->drawable.y != 0)
+ {
+ fprintf(stderr, "nxagentModifyPixmapHeader: PANIC! Pixmap at [%p] has x [%d] and y [%d].\n",
+ (void *) pPixmap, pPixmap->drawable.x, pPixmap->drawable.y);
+
+ FatalError("nxagentModifyPixmapHeader: PANIC! Pixmap has x or y greater than zero.");
+ }
+
+ #endif
+ }
+
+ return True;
+}
+
+static void nxagentPixmapMatchID(void *p0, XID x1, void *p2)
+{
+ PixmapPtr pPixmap = (PixmapPtr)p0;
+ struct nxagentPixmapPair *pPair = p2;
+
+ if ((pPair -> pMap == NULL) && (nxagentPixmap(pPixmap) == pPair -> pixmap))
+ {
+ pPair -> pMap = pPixmap;
+ }
+}
+
+PixmapPtr nxagentPixmapPtr(Pixmap pixmap)
+{
+ int i;
+ struct nxagentPixmapPair pair;
+
+ if (pixmap == None)
+ {
+ return NULL;
+ }
+
+ pair.pixmap = pixmap;
+ pair.pMap = NULL;
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP,
+ nxagentPixmapMatchID, &pair);
+
+ for (i = 0; (pair.pMap == NULL) && (i < MAXCLIENTS); i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_PIXMAP,
+ nxagentPixmapMatchID, &pair);
+ }
+ }
+
+ #ifdef WARNING
+
+ if (pair.pMap == NULL)
+ {
+ fprintf(stderr, "nxagentFindPixmap: WARNING! Failed to find "
+ "remote pixmap [%ld].\n", (long int) pair.pixmap);
+ }
+ else if (nxagentDrawableStatus((DrawablePtr) pair.pMap) == NotSynchronized)
+ {
+ fprintf(stderr, "WARNING! Rootless icon at [%p] [%d,%d] is not synchronized.\n",
+ (void *) pair.pMap, pair.pMap -> drawable.width,
+ pair.pMap -> drawable.height);
+ }
+
+ #endif
+
+ return pair.pMap;
+}
+
+/*
+ * Reconnection stuff.
+ */
+
+int nxagentDestroyNewPixmapResourceType(void * p, XID id)
+{
+ /*
+ * Address of the destructor is set in Init.c.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyNewPixmapResourceType: Destroying mirror id [%ld] for pixmap at [%p].\n",
+ nxagentPixmapPriv((PixmapPtr) p) -> mid, (void *) p);
+ #endif
+
+ nxagentPixmapPriv((PixmapPtr) p) -> mid = None;
+
+ return True;
+}
+
+void nxagentDisconnectPixmap(void *p0, XID x1, void *p2)
+{
+ PixmapPtr pPixmap = (PixmapPtr) p0;
+
+ #ifdef TEST
+ Bool *pBool;
+
+ pBool = (Bool*) p2;
+
+ fprintf(stderr, "nxagentDisconnectPixmap: Called with bool [%d] and pixmap at [%p].\n",
+ *pBool, (void *) pPixmap);
+
+ fprintf(stderr, "nxagentDisconnectPixmap: Virtual pixmap is [%ld].\n",
+ nxagentPixmap(pPixmap));
+ #endif
+
+ nxagentPixmap(pPixmap) = None;
+
+ if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized)
+ {
+ nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND);
+
+ nxagentDestroyCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP);
+ }
+}
+
+Bool nxagentDisconnectAllPixmaps()
+{
+ int r = 1;
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: Going to iterate through pixmap resources.\n");
+ #endif
+
+ /*
+ * The RT_NX_PIXMAP resource type is allocated
+ * only on the server client, so we don't need
+ * to find it through the other clients too.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, nxagentDisconnectPixmap, &r);
+
+ #ifdef WARNING
+
+ if (r == 0)
+ {
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect "
+ "pixmap for client [%d].\n", serverClient -> index);
+ }
+
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; r = 1, i++)
+ {
+ if (clients[i])
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: Going to disconnect pixmaps of client [%d].\n", i);
+ #endif
+
+ FindClientResourcesByType(clients[i], RT_PIXMAP, nxagentDisconnectPixmap, &r);
+
+ #ifdef WARNING
+
+ if (r == 0)
+ {
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect "
+ "pixmap for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ #ifdef WARNING
+
+ if (r == 0)
+ {
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: WARNING! Failed to disconnect "
+ "pixmap for client [%d].\n", i);
+ }
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectAllPixmaps: Pixmaps disconnection completed.\n");
+ #endif
+
+ return r;
+}
+
+void nxagentReconnectPixmap(void *p0, XID x1, void *p2)
+{
+ PixmapPtr pPixmap = (PixmapPtr) p0;
+ Bool *pBool = (Bool*) p2;
+ nxagentPrivPixmapPtr pPixmapPriv;
+
+ if (*pBool == 0 || pPixmap == NULL ||
+ NXDisplayError(nxagentDisplay) == 1)
+ {
+ *pBool = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPixmap: Ignoring pixmap at [%p] while "
+ "recovering from the error.\n", (void *) pPixmap);
+ #endif
+
+ return;
+ }
+ else if (pPixmap == nxagentDefaultScreen -> pScratchPixmap)
+ {
+ /*
+ * Every time the scratch pixmap is used its
+ * data is changed, so we don't need to recon-
+ * nect it.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPixmap: Ignoring scratch pixmap at [%p].\n",
+ (void *) pPixmap);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPixmap: Called with result [%d] and pixmap at [%p].\n",
+ *pBool, (void *) pPixmap);
+
+ fprintf(stderr, "nxagentReconnectPixmap: Virtual pixmap is at [%p] picture is at [%p].\n",
+ (void *) nxagentPixmapPriv(pPixmap) -> pVirtualPixmap,
+ (void *) nxagentPixmapPriv(pPixmap) -> pPicture);
+ #endif
+
+ pPixmapPriv = nxagentPixmapPriv(pPixmap);
+
+ if (pPixmap -> drawable.width && pPixmap -> drawable.height)
+ {
+ pPixmapPriv -> id = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[pPixmap -> drawable.pScreen -> myNum],
+ pPixmap -> drawable.width,
+ pPixmap -> drawable.height,
+ pPixmap -> drawable.depth);
+
+ nxagentPixmap(pPixmapPriv -> pVirtualPixmap) = pPixmapPriv -> id;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPixmap: Created virtual pixmap with id [%ld] for pixmap at [%p].\n",
+ nxagentPixmap(pPixmap), (void *) pPixmap);
+ #endif
+
+ if (pPixmap == (PixmapPtr) nxagentDefaultScreen -> devPrivate)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectPixmap: WARNING! Pixmap is root screen. Returning.\n");
+ #endif
+
+ return;
+ }
+
+ nxagentSplitTrap = 1;
+
+ *pBool = nxagentSynchronizeDrawableData((DrawablePtr) pPixmap, NEVER_BREAK, NULL);
+
+ nxagentSplitTrap = 0;
+
+ if (*pBool == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentReconnectPixmap: PANIC! Failed to synchronize the pixmap.\n");
+ #endif
+ }
+
+
+ if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized)
+ {
+ if (nxagentIsCorruptedBackground(pPixmap) == 1)
+ {
+ nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_BACKGROUND);
+
+ nxagentFillRemoteRegion((DrawablePtr) pPixmap,
+ nxagentCorruptedRegion((DrawablePtr) pPixmap));
+ }
+ else
+ {
+ nxagentAllocateCorruptedResource((DrawablePtr) pPixmap, RT_NX_CORR_PIXMAP);
+ }
+ }
+ }
+}
+
+Bool nxagentReconnectAllPixmaps(void *p0)
+{
+ Bool result = 1;
+
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllPixmaps: Going to recreate all pixmaps.\n");
+ #endif
+
+ /*
+ * Reset the geometry and alpha information
+ * used by proxy to unpack the packed images.
+ */
+
+ nxagentResetVisualCache();
+
+ nxagentResetAlphaCache();
+
+ /*
+ * The RT_NX_PIXMAP resource type is allocated
+ * only on the server client, so we don't need
+ * to find it through the other clients too.
+ */
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP, nxagentReconnectPixmap, &result);
+
+ #ifdef WARNING
+
+ if (result == 0)
+ {
+ fprintf(stderr, "nxagentReconnectAllPixmaps: WARNING! Failed to reconnect "
+ "pixmap for client [%d].\n", serverClient -> index);
+ }
+
+ #endif
+
+ for (i = 0, result = 1; i < MAXCLIENTS; result = 1, i++)
+ {
+ if (clients[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllPixmaps: Going to reconnect pixmaps of client [%d].\n", i);
+ #endif
+
+ /*
+ * Let the pixmap be reconnected as it was an
+ * image request issued by the client owning
+ * the resource. The client index is used as
+ * a subscript by the image routines to cache
+ * the data per-client.
+ */
+
+ FindClientResourcesByType(clients[i], RT_PIXMAP, nxagentReconnectPixmap, &result);
+
+ #ifdef WARNING
+
+ if (result == 0)
+ {
+ fprintf(stderr, "nxagentReconnectAllPixmaps: WARNING! Failed to reconnect "
+ "pixmap for client [%d].\n", serverClient -> index);
+ }
+
+ #endif
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllPixmaps: Pixmaps reconnection completed.\n");
+ #endif
+
+ return result;
+}
+
+#ifdef TEST
+
+static void nxagentCheckOnePixmapIntegrity(void *p0, XID x1, void *p2)
+{
+ PixmapPtr pPixmap = (PixmapPtr) p0;
+ Bool *pBool = (Bool*) p2;
+
+ if (*pBool == False)
+ {
+ return;
+ }
+
+ if (pPixmap == nxagentDefaultScreen -> devPrivate)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckOnePixmapIntegrity: pixmap %p is screen.\n",
+ (void *) pPixmap);
+ #endif
+
+ return;
+ }
+
+ if (pPixmap == nxagentDefaultScreen -> PixmapPerDepth[0])
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckOnePixmapIntegrity: pixmap %p is default stipple of screen.\n",
+ (void *) pPixmap);
+ #endif
+
+ return;
+ }
+
+ *pBool = nxagentCheckPixmapIntegrity(pPixmap);
+}
+
+Bool nxagentCheckPixmapIntegrity(PixmapPtr pPixmap)
+{
+ Bool integrity = 1;
+ XImage *image;
+ char *data;
+ int format;
+ unsigned long plane_mask = AllPlanes;
+ unsigned int width, height, length, depth;
+ PixmapPtr pVirtual = nxagentVirtualPixmap(pPixmap);
+
+ width = pPixmap -> drawable.width;
+ height = pPixmap -> drawable.height;
+ depth = pPixmap -> drawable.depth;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ if (width && height)
+ {
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ data = malloc(length);
+
+ if (data == NULL)
+ {
+ FatalError("nxagentCheckPixmapIntegrity: Failed to allocate a buffer of size %d.\n", length);
+ }
+
+ image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), 0, 0,
+ width, height, plane_mask, format);
+ if (image == NULL)
+ {
+ FatalError("XGetImage: Failed.\n");
+
+ free(data);
+
+ return False;
+ }
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Image from X has length [%d] and checksum [0x%s].\n",
+ length, nxagentChecksum(image->data, length));
+ #endif
+
+ NXCleanImage(image);
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Image after clean has checksum [0x%s].\n",
+ nxagentChecksum(image->data, length));
+ #endif
+
+ fbGetImage((DrawablePtr) pVirtual, 0, 0, width, height, format, plane_mask, data);
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Image from FB has length [%d] and checksum [0x%s].\n",
+ length, nxagentChecksum(data, length));
+ #endif
+
+ if (image != NULL && memcmp(image -> data, data, length) != 0)
+ {
+ integrity = 0;
+ }
+ else
+ {
+ integrity = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Pixmap at [%p] has been realized. "
+ "Now remote and frambuffer data are synchronized.\n", (void *) pPixmap);
+ #endif
+ }
+
+ #ifdef WARNING
+
+ if (integrity == 0)
+ {
+
+ int i;
+ char *p, *q;
+
+ for (i = 0, p = image -> data, q = data; i < length; i++)
+ {
+ if (p[i] != q[i])
+ {
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Byte [%d] image -> data [%d] data [%d]. "
+ "Buffers differ!\n", i, p[i], q[i]);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Byte [%d] image -> data [%d] data [%d].\n",
+ i, p[i], q[i]);
+ }
+ }
+
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Pixmap at [%p] width [%d], height [%d], has been realized "
+ "but the data buffer still differs.\n", (void *) pPixmap, width, height);
+
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: bytes_per_line [%d] byte pad [%d] format [%d].\n",
+ image -> bytes_per_line, nxagentImagePad(width, height, 0, depth), image -> format);
+
+ FatalError("nxagentCheckPixmapIntegrity: Image is corrupted!!\n");
+
+ }
+
+ #endif
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckPixmapIntegrity: Ignored pixmap at [%p] with geometry [%d] [%d].\n",
+ (void *) pPixmap, width, height);
+ #endif
+ }
+
+ return integrity;
+}
+
+Bool nxagentCheckAllPixmapIntegrity()
+{
+ int i;
+ Bool imageIsGood = True;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckAllPixmapIntegrity\n");
+ #endif
+
+ FindClientResourcesByType(clients[serverClient -> index], RT_NX_PIXMAP,
+ nxagentCheckOnePixmapIntegrity, &imageIsGood);
+
+ for (i = 0; (i < MAXCLIENTS) && (imageIsGood); i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], RT_PIXMAP,
+ nxagentCheckOnePixmapIntegrity, &imageIsGood);
+
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCheckAllPixmapIntegrity: pixmaps integrity = %d.\n", imageIsGood);
+ #endif
+
+ return imageIsGood;
+}
+
+#endif
+
+void nxagentSynchronizeShmPixmap(DrawablePtr pDrawable, int xPict, int yPict,
+ int wPict, int hPict)
+{
+ GCPtr pGC;
+ char *data;
+ int width, height;
+ int depth, length, format;
+ CARD32 attributes[3];
+
+ int saveTrap;
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pDrawable) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSynchronizeShmPixmap: WARNING! Synchronizing shared pixmap at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ pGC = nxagentGetScratchGC(pDrawable -> depth, pDrawable -> pScreen);
+
+ attributes[0] = 0x228b22;
+ attributes[1] = 0xffffff;
+ attributes[2] = FillSolid;
+
+ ChangeGC(pGC, GCForeground | GCBackground | GCFillStyle, attributes);
+
+ ValidateGC(pDrawable, pGC);
+
+ width = (wPict != 0 && wPict <= pDrawable -> width) ? wPict : pDrawable -> width;
+ height = (hPict != 0 && hPict <= pDrawable -> height) ? hPict : pDrawable -> height;
+
+ depth = pDrawable -> depth;
+
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ saveTrap = nxagentGCTrap;
+
+ nxagentGCTrap = 0;
+
+ nxagentSplitTrap = 1;
+
+ nxagentFBTrap = 1;
+
+ if ((data = malloc(length)) != NULL)
+ {
+ fbGetImage(nxagentVirtualDrawable(pDrawable), xPict, yPict,
+ width, height, format, 0xffffffff, data);
+
+ nxagentPutImage(pDrawable, pGC, depth, xPict, yPict,
+ width, height, 0, format, data);
+
+ free(data);
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "nxagentSynchronizeShmPixmap: WARNING! Failed to allocate memory for the operation.\n");
+ }
+ #endif
+
+ nxagentGCTrap = saveTrap;
+
+ nxagentSplitTrap = 0;
+
+ nxagentFBTrap = 0;
+
+ nxagentFreeScratchGC(pGC);
+ }
+}
+
+#ifdef DUMP
+
+/*
+ * This function is useful to visualize a pixmap and check
+ * its data consistency. To avoid the creation of many
+ * windows, one pixmap only can be monitored at a time.
+ */
+
+Bool nxagentPixmapOnShadowDisplay(PixmapPtr pMap)
+{
+ static Display *shadow;
+ static Window win;
+ static int init = True;
+ static int showTime;
+ static PixmapPtr pPixmap;
+ static int depth;
+ static int width;
+ static int height;
+ static int length;
+ static unsigned int format;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ Visual *pVisual;
+ char *data = NULL;
+
+
+ if (init)
+ {
+ if (pMap == NULL)
+ {
+ return False;
+ }
+ else
+ {
+ pPixmap = pMap;
+ }
+
+ depth = pPixmap -> drawable.depth;
+ width = pPixmap -> drawable.width;
+ height = pPixmap -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ shadow = XOpenDisplay("localhost:0");
+
+ if (shadow == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Shadow display not opened.\n");
+ #endif
+
+ return False;
+ }
+
+ init = False;
+
+ win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0,
+ width, height, 0, 0xFFCC33, 0xFF);
+
+ XMapWindow(shadow, win);
+ XClearWindow(shadow, win);
+ }
+
+/*
+FIXME: If the pixmap has a different depth from the window, the
+ XPutImage returns a BadMatch. For example this may happens if
+ the Render extension is enabled.
+ Can we fix this creating a new pixmap?
+*/
+
+ if (DisplayPlanes(shadow, DefaultScreen(shadow)) != depth)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPixmapOnShadowDisplay: Pixmap and Window depths [%d - %d] are not equals!\n",
+ depth, DisplayPlanes(shadow, DefaultScreen(shadow)));
+ #endif
+
+ return False;
+ }
+
+ /*
+ * If the framebuffer is updated continuously, the nxagent
+ * visualization become too much slow.
+ */
+
+ if ((GetTimeInMillis() - showTime) < 500)
+ {
+ return False;
+ }
+
+ showTime = GetTimeInMillis();
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ return False;
+ }
+
+ fbGetImage((DrawablePtr) nxagentVirtualPixmap(pPixmap), 0, 0,
+ width, height, format, AllPlanes, data);
+
+ pVisual = nxagentImageVisual((DrawablePtr) pPixmap, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPixmapOnShadowDisplay: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ image = XCreateImage(nxagentDisplay, pVisual,
+ depth, format, 0, (char *) data,
+ width, height, BitmapPad(nxagentDisplay),
+ nxagentImagePad(width, format, 0, depth));
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentPixmapOnShadowDisplay: XCreateImage failed.\n");
+ #endif
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+
+ return False;
+ }
+
+ value.foreground = 0xff0000;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(shadow, win, GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height);
+
+ XFreeGC(shadow, gc);
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+
+ return True;
+}
+
+Bool nxagentFbOnShadowDisplay()
+{
+ static Display *shadow;
+ static Window win;
+ static int init = True;
+ static int showTime;
+ static int prevWidth, prevHeight;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ Visual *pVisual;
+ WindowPtr pWin = screenInfo.screens[0]->root;
+ unsigned int format;
+ int depth, width, height, length;
+ char *data = NULL;
+
+
+ if (pWin == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: The parent window is NULL.\n");
+ #endif
+
+ return False;
+ }
+
+ depth = pWin -> drawable.depth;
+ width = pWin -> drawable.width;
+ height = pWin -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ if (init)
+ {
+ shadow = XOpenDisplay("localhost:0");
+
+ if (shadow == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Shadow display not opened.\n");
+ #endif
+
+ return False;
+ }
+
+ init = False;
+
+ prevWidth = width;
+ prevHeight = height;
+
+ win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0,
+ width, height, 0, 0xFFCC33, 0xFF);
+
+ XMapWindow(shadow, win);
+ XClearWindow(shadow, win);
+ }
+
+ if (DisplayPlanes(shadow, DefaultScreen(shadow)) != depth)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: Depths [%d - %d] are not equals!\n",
+ depth, DisplayPlanes(shadow, DefaultScreen(shadow)));
+ #endif
+
+ return False;
+ }
+
+ /*
+ * If the framebuffer is updated continuously, the nxagent
+ * visualization becomes too much slow.
+ */
+
+ if ((GetTimeInMillis() - showTime) < 500)
+ {
+ return False;
+ }
+
+ showTime = GetTimeInMillis();
+
+ /*
+ * If the root window is resized, also the window on shadow
+ * display must be resized.
+ */
+
+ if (prevWidth != width || prevHeight != height)
+ {
+ XWindowChanges values;
+
+ prevWidth = width;
+ prevHeight = height;
+
+ values.width = width;
+ values.height = height;
+ XConfigureWindow(shadow, win, CWWidth | CWHeight, &values);
+ }
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Failed to allocate memory for the operation.\n");
+ #endif
+
+ return False;
+ }
+
+ fbGetImage((DrawablePtr)pWin, 0, 0,
+ width, height, format, AllPlanes, data);
+
+ pVisual = nxagentImageVisual((DrawablePtr) pWin, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ image = XCreateImage(nxagentDisplay, pVisual,
+ depth, format, 0, (char *) data,
+ width, height, BitmapPad(nxagentDisplay),
+ nxagentImagePad(width, format, 0, depth));
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbOnShadowDisplay: XCreateImage failed.\n");
+ #endif
+
+ if (data)
+ {
+ free(data);
+ }
+
+ return False;
+ }
+
+ value.foreground = 0xff0000;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(shadow, win, GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height);
+
+ XFreeGC(shadow, gc);
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+
+ return True;
+}
+
+#endif
+
+#ifdef DEBUG
+
+void nxagentPrintResourceTypes()
+{
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_PIXMAP [%lu].\n", (unsigned long) RT_PIXMAP);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_PIXMAP [%lu].\n", (unsigned long) RT_NX_PIXMAP);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_GC [%lu].\n", (unsigned long) RT_GC);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_GC [%lu].\n", (unsigned long) RT_NX_GC);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_FONT [%lu].\n", (unsigned long) RT_FONT);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_NX_FONT [%lu].\n", (unsigned long) RT_NX_FONT);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_CURSOR [%lu].\n", (unsigned long) RT_CURSOR);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_WINDOW [%lu].\n", (unsigned long) RT_WINDOW);
+ fprintf(stderr, "nxagentPrintResourceTypes: RT_COLORMAP [%lu].\n", (unsigned long) RT_COLORMAP);
+}
+
+void nxagentPrintResourcePredicate(void *value, XID id, XID type, void *cdata)
+{
+ fprintf(stderr, "nxagentPrintResourcePredicate: Resource [%p] id [%lu] type [%lu].\n",
+ (void *) value, (unsigned long) id, (unsigned long) type);
+}
+
+void nxagentPrintResources()
+{
+ Bool result;
+ int i;
+
+ nxagentPrintResourceTypes();
+
+ for (i = 0; i < MAXCLIENTS; i++)
+ {
+ if (clients[i])
+ {
+ fprintf(stderr, "nxagentPrintResources: Printing resources for client [%d]:\n",
+ i);
+
+ FindAllClientResources(clients[i], nxagentPrintResourcePredicate, &result);
+ }
+ }
+}
+
+#endif
+
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h b/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h
new file mode 100644
index 000000000..00cc39c5f
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pixmaps.h
@@ -0,0 +1,145 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Pixmap_H__
+#define __Pixmap_H__
+
+#include "resource.h"
+#include "Split.h"
+
+extern RESTYPE RT_NX_PIXMAP;
+
+/*
+ * Pixmap privates structure.
+ */
+
+typedef struct
+{
+ Pixmap id;
+ XID mid;
+
+ Bool isVirtual;
+ Bool isShared;
+
+ PixmapPtr pVirtualPixmap;
+ PixmapPtr pRealPixmap;
+
+ void *pPicture;
+
+ RegionPtr corruptedRegion;
+
+ int corruptedBackground;
+
+ int containGlyphs;
+ int containTrapezoids;
+
+ int usageCounter;
+
+ XID corruptedBackgroundId;
+ XID corruptedId;
+
+ PixmapPtr synchronizationBitmap;
+
+ Time corruptedTimestamp;
+
+ SplitResourcePtr splitResource;
+
+ int isBackingPixmap;
+
+} nxagentPrivPixmapRec;
+
+typedef nxagentPrivPixmapRec *nxagentPrivPixmapPtr;
+
+extern int nxagentPixmapPrivateIndex;
+
+/*
+ * Pixmap privates macro.
+ */
+
+#define nxagentPixmapPriv(pPixmap) \
+ ((nxagentPrivPixmapPtr)((pPixmap) -> devPrivates[nxagentPixmapPrivateIndex].ptr))
+
+#define nxagentPixmap(pPixmap) (nxagentPixmapPriv(pPixmap) -> id)
+
+#define nxagentPixmapIsVirtual(pPixmap) \
+ (nxagentPixmapPriv(pPixmap) -> isVirtual)
+
+#define nxagentIsShmPixmap(pPixmap) \
+ (nxagentPixmapPriv(pPixmap) -> isShared)
+
+#define nxagentRealPixmap(pPixmap) \
+ (nxagentPixmapPriv(pPixmap) -> pRealPixmap)
+
+#define nxagentVirtualPixmap(pPixmap) \
+ (nxagentPixmapPriv(pPixmap) -> isVirtual ? pPixmap : \
+ nxagentPixmapPriv(pPixmap) -> pVirtualPixmap)
+
+#define nxagentPixmapCorruptedRegion(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedRegion)
+
+#define nxagentPixmapContainGlyphs(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> containGlyphs)
+
+#define nxagentPixmapContainTrapezoids(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> containTrapezoids)
+
+#define nxagentIsCorruptedBackground(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedBackground)
+
+#define nxagentPixmapUsageCounter(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> usageCounter)
+
+#define nxagentPixmapTimestamp(pPixmap) \
+ (nxagentPixmapPriv(nxagentRealPixmap(pPixmap)) -> corruptedTimestamp)
+
+PixmapPtr nxagentPixmapPtr(Pixmap pixmap);
+
+PixmapPtr nxagentCreatePixmap(ScreenPtr pScreen, int width,
+ int height, int depth, unsigned usage_hint);
+
+Bool nxagentDestroyPixmap(PixmapPtr pPixmap);
+
+RegionPtr nxagentPixmapToRegion(PixmapPtr pPixmap);
+
+Bool nxagentModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
+ int bitsPerPixel, int devKind, void * pPixData);
+
+RegionPtr nxagentCreateRegion(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int width, int height);
+
+void nxagentReconnectPixmap(void *p0, XID x1, void *p2);
+Bool nxagentReconnectAllPixmaps(void *p0);
+void nxagentDisconnectPixmap(void *p0, XID x1, void* p2);
+Bool nxagentDisconnectAllPixmaps(void);
+
+int nxagentDestroyNewPixmapResourceType(void * p, XID id);
+
+void nxagentSynchronizeShmPixmap(DrawablePtr pDrawable, int xPict, int yPict,
+ int wPict, int hPict);
+
+Bool nxagentPixmapOnShadowDisplay(PixmapPtr pMap);
+Bool nxagentFbOnShadowDisplay();
+
+#endif /* __Pixmap_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pointer.c b/nx-X11/programs/Xserver/hw/nxagent/Pointer.c
new file mode 100644
index 000000000..c59230724
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.c
@@ -0,0 +1,199 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "mipointer.h"
+
+#include "Agent.h"
+#include "Args.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Pointer.h"
+#include "Events.h"
+#include "Options.h"
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * The nxagentReversePointerMap array is used to
+ * memorize remote display pointer map.
+ */
+
+unsigned char nxagentReversePointerMap[MAXBUTTONS];
+
+void nxagentChangePointerControl(DeviceIntPtr pDev, PtrCtrl *ctrl)
+{
+ /*
+ * The original behaviour was to reset the pointer settings
+ * (acceleration and alas) to the default values. What the
+ * average user expects, on the contrary, is to have agent
+ * inheriting whatever value is set on the real X display.
+ * Having to reflect changes made inside the agent session,
+ * the correct behavior would be saving the original values
+ * and restoring them as soon as focus leaves the agent's
+ * window.
+ */
+
+ if (nxagentOption(DeviceControl) == True)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangePointerControl: WARNING! Propagating changes to pointer settings.\n");
+ #endif
+
+ XChangePointerControl(nxagentDisplay, True, True,
+ ctrl->num, ctrl->den, ctrl->threshold);
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangePointerControl: WARNING! Not propagating changes to pointer settings.\n");
+ #endif
+}
+
+int nxagentPointerProc(DeviceIntPtr pDev, int onoff)
+{
+ CARD8 map[MAXBUTTONS];
+ int nmap;
+ int i;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_INIT].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ nmap = XGetPointerMapping(nxagentDisplay, map, MAXBUTTONS);
+ for (i = 0; i <= nmap; i++)
+ map[i] = i; /* buttons are already mapped */
+ InitPointerDeviceStruct((DevicePtr) pDev, map, nmap,
+ miPointerGetMotionEvents,
+ nxagentChangePointerControl,
+ miPointerGetMotionBufferSize());
+ break;
+ case DEVICE_ON:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_ON].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ nxagentInitPointerMap();
+
+ nxagentEnablePointerEvents();
+
+ break;
+
+ case DEVICE_OFF:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_OFF].\n");
+ #endif
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return Success;
+ }
+
+ nxagentDisablePointerEvents();
+
+ break;
+
+ case DEVICE_CLOSE:
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPointerProc: Called for [DEVICE_CLOSE].\n");
+ #endif
+
+ break;
+ }
+
+ return Success;
+}
+
+void nxagentInitPointerMap(void)
+{
+ int numButtons;
+
+ int i;
+
+ unsigned char pointerMap[MAXBUTTONS];
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentInitPointerMap: Going to retrieve the "
+ "pointer map from remote display.\n");
+ #endif
+
+ numButtons = XGetPointerMapping(nxagentDisplay, pointerMap, MAXBUTTONS);
+
+ /*
+ * Computing revers pointer map.
+ */
+
+ for (i = 1; i <= numButtons; i++)
+ {
+ nxagentReversePointerMap[pointerMap[i - 1]] = i;
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Pointer.h b/nx-X11/programs/Xserver/hw/nxagent/Pointer.h
new file mode 100644
index 000000000..85162d4a5
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Pointer.h
@@ -0,0 +1,62 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Pointer_H__
+#define __Pointer_H__
+
+#define MAXBUTTONS 256
+
+#define NXAGENT_POINTER_EVENT_MASK \
+ (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask)
+
+/*
+ * The nxagentReversePointerMap array is used to
+ * memorize remote display pointer map.
+ */
+
+extern unsigned char nxagentReversePointerMap[MAXBUTTONS];
+
+void nxagentChangePointerControl(DeviceIntPtr pDev, PtrCtrl *ctrl);
+
+int nxagentPointerProc(DeviceIntPtr pDev, int onoff);
+
+void nxagentInitPointerMap(void);
+
+#endif /* __Pointer_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c
new file mode 100644
index 000000000..fb2303549
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.c
@@ -0,0 +1,849 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <signal.h>
+
+#include "X.h"
+#include "Xproto.h"
+#include "Xpoll.h"
+#include "mi.h"
+#include "fb.h"
+#include "inputstr.h"
+
+#include "Agent.h"
+#include "Atoms.h"
+#include "Drawable.h"
+#include "Client.h"
+#include "Reconnect.h"
+#include "Display.h"
+#include "Dialog.h"
+#include "Screen.h"
+#include "Windows.h"
+#include "Events.h"
+#include "Dialog.h"
+#include "Args.h"
+#include "Font.h"
+#include "GCs.h"
+#include "Trap.h"
+#include "Keyboard.h"
+#include "Composite.h"
+#include "Millis.h"
+#include "Splash.h"
+#include "Error.h"
+#include "Keystroke.h"
+
+#ifdef XKB
+#include "XKBsrv.h"
+#endif
+
+#include <nx/NX.h>
+#include "compext/Compext.h"
+#include <nx/NXalert.h>
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define NXAGENT_RECONNECT_DEFAULT_MESSAGE_SIZE 32
+
+extern Bool nxagentReconnectAllCursor(void*);
+extern Bool nxagentReconnectAllColormap(void*);
+extern Bool nxagentReconnectAllWindows(void*);
+extern Bool nxagentReconnectAllGlyphSet(void*);
+extern Bool nxagentReconnectAllPictFormat(void*);
+extern Bool nxagentReconnectAllPicture(void*);
+
+extern Bool nxagentDisconnectAllPicture(void);
+extern Bool nxagentDisconnectAllWindows(void);
+extern Bool nxagentDisconnectAllCursor(void);
+
+extern Bool nxagentReconnectFailedFonts(void*);
+extern Bool nxagentInstallFontServerPath(void);
+extern Bool nxagentUninstallFontServerPath(void);
+
+extern void nxagentRemoveXConnection(void);
+
+extern void nxagentInitPointerMap(void);
+
+static char *nxagentGetReconnectError(void);
+
+void nxagentInitializeRecLossyLevel(void);
+
+static char *nxagentReconnectErrorMessage = NULL;
+static int nxagentReconnectErrorId;
+
+extern Bool nxagentRenderEnable;
+
+extern char *nxagentKeyboard;
+
+enum SESSION_STATE nxagentSessionState = SESSION_STARTING;
+
+struct nxagentExceptionStruct nxagentException = {0, 0};
+
+enum RECONNECTION_STEP
+{
+ DISPLAY_STEP = 0,
+ SCREEN_STEP,
+ FONT_STEP,
+ PIXMAP_STEP,
+ GC_STEP,
+ CURSOR_STEP,
+ COLORMAP_STEP,
+ WINDOW_STEP,
+ GLYPHSET_STEP,
+ PICTFORMAT_STEP,
+ PICTURE_STEP,
+ STEP_NONE
+};
+
+void *reconnectLossyLevel[STEP_NONE];
+
+static enum RECONNECTION_STEP failedStep;
+
+#include <limits.h>
+
+/*
+ * Path of state File
+ */
+char stateFile[PATH_MAX];
+
+
+void setStatePath(char* path)
+{
+ strncpy(stateFile, path, PATH_MAX-1);
+}
+
+void saveAgentState(char* state)
+{
+ FILE* fptr;
+ if(strlen(stateFile))
+ {
+ fptr=fopen(stateFile, "w");
+ if(!fptr)
+ return;
+ fprintf(fptr,"%s", state);
+ fclose(fptr);
+ }
+}
+
+
+int nxagentHandleConnectionStates(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Handling Exception with "
+ "state [%s] and transport [%d] and generation [%ld].\n",
+ DECODE_SESSION_STATE(nxagentSessionState), NXTransRunning(NX_FD_ANY), serverGeneration);
+ fprintf(stderr, "nxagentHandleConnectionStates: Entering with nxagentException.sigHup = [%d], "
+ "nxagentException.ioError = [%d]\n",
+ nxagentException.sigHup, nxagentException.ioError);
+ #endif
+
+ if (nxagentException.sigHup > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got SIGHUP in the exception flags.\n");
+ #endif
+
+ nxagentException.sigHup = 0;
+
+ if (nxagentSessionState == SESSION_UP)
+ {
+ if (nxagentOption(Persistent))
+ {
+ nxagentSessionState = SESSION_GOING_DOWN;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Handling "
+ "signal [SIGHUP] by disconnecting the agent.\n");
+
+ #endif
+
+ }
+ else
+ {
+ nxagentTerminateSession();
+ }
+ }
+ else if (nxagentSessionState == SESSION_STARTING)
+ {
+ nxagentTerminateSession();
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentHandleConnectionStates: Handling signal [SIGHUP] by terminating the agent.\n");
+ #endif
+ }
+ else if (nxagentSessionState == SESSION_DOWN &&
+ NXTransRunning(NX_FD_ANY) == 0)
+ {
+ nxagentSessionState = SESSION_GOING_UP;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Handling signal [SIGHUP] by reconnecting the agent.\n");
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Handling signal with state [%s] and exception [%d].\n",
+ DECODE_SESSION_STATE(nxagentSessionState), dispatchException);
+ #endif
+ }
+ }
+
+ if (nxagentNeedConnectionChange() == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Calling nxagentHandleConnectionChanges "
+ "with ioError [%d] sigHup [%d].\n", nxagentException.ioError, nxagentException.sigHup);
+ #endif
+
+ nxagentHandleConnectionChanges();
+ }
+
+ if (nxagentException.ioError > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error in the exception flags.\n");
+ #endif
+/*
+TODO: This should be reset only when
+ the state became SESSION_DOWN.
+*/
+ nxagentException.ioError = 0;
+
+ if (nxagentOption(Persistent) == 1 && nxagentSessionState != SESSION_STARTING)
+ {
+ if (nxagentSessionState == SESSION_UP)
+ {
+ if ((dispatchException & DE_TERMINATE) == 0)
+ {
+ fprintf(stderr, "Session: Display failure detected at '%s'.\n", GetTimeAsString());
+
+ fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString());
+ saveAgentState("SUSPENDING");
+ }
+
+ nxagentDisconnectSession();
+ }
+ else if (nxagentSessionState == SESSION_GOING_DOWN)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session "
+ "[SESSION_GOING_DOWN].\n");
+ #endif
+ }
+ else if (nxagentSessionState == SESSION_GOING_UP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session "
+ "[SESSION_GOING_UP].\n");
+ #endif
+
+ nxagentSessionState = SESSION_GOING_DOWN;
+
+ nxagentSetReconnectError(FAILED_RESUME_DISPLAY_BROKEN_ALERT,
+ "Got I/O error during reconnect.");
+
+ nxagentChangeOption(Fullscreen, False);
+
+ return 1;
+ }
+ else if (nxagentSessionState == SESSION_DOWN)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session "
+ "[SESSION_DOWN]. Ignoring.\n");
+ #endif
+
+ return 1;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionStates: Got I/O error with session "
+ "[%d].\n", nxagentSessionState);
+ #endif
+ }
+
+ nxagentSessionState = SESSION_DOWN;
+
+ if ((dispatchException & DE_TERMINATE) == 0)
+ {
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session suspended at '%s' timestamp [%lu].\n", GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session suspended at '%s'.\n", GetTimeAsString());
+ #endif
+ }
+ saveAgentState("SUSPENDED");
+
+ nxagentResetDisplayHandlers();
+
+ return 1;
+ }
+
+ fprintf(stderr, "Info: Disconnected from display '%s'.\n", nxagentDisplayName);
+
+ nxagentTerminateSession();
+
+ return -1;
+ }
+
+ return 0;
+}
+
+void nxagentInitializeRecLossyLevel()
+{
+ *(int *)reconnectLossyLevel[DISPLAY_STEP] = 0;
+ *(int *)reconnectLossyLevel[SCREEN_STEP] = 0;
+ *(int *)reconnectLossyLevel[FONT_STEP] = 0;
+ *(int *)reconnectLossyLevel[PIXMAP_STEP] = 0;
+ *(int *)reconnectLossyLevel[GC_STEP] = 0;
+ *(int *)reconnectLossyLevel[CURSOR_STEP] = 0;
+ *(int *)reconnectLossyLevel[COLORMAP_STEP] = 0;
+ *(int *)reconnectLossyLevel[WINDOW_STEP] = 0;
+ *(int *)reconnectLossyLevel[GLYPHSET_STEP] = 0;
+ *(int *)reconnectLossyLevel[PICTFORMAT_STEP] = 0;
+ *(int *)reconnectLossyLevel[PICTURE_STEP] = 0;
+}
+
+void nxagentInitReconnector(void)
+{
+ nxagentReconnectTrap = 0;
+
+ reconnectLossyLevel[DISPLAY_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[SCREEN_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[FONT_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[PIXMAP_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[GC_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[CURSOR_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[COLORMAP_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[WINDOW_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[GLYPHSET_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[PICTFORMAT_STEP] = malloc(sizeof(int));
+ reconnectLossyLevel[PICTURE_STEP] = malloc(sizeof(int));
+}
+
+void nxagentDisconnectSession(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectSession: Disconnecting session with state [%s].\n",
+ DECODE_SESSION_STATE(nxagentSessionState));
+ #endif
+
+ /*
+ * Force an I/O error on the display
+ * and wait until the NX transport
+ * is gone.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectSession: Disconnecting the X display.\n");
+ #endif
+
+ nxagentWaitDisplay();
+
+ /*
+ * Prepare for the next reconnection.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectSession: Disconnecting all X resources.\n");
+ #endif
+
+ nxagentInitializeRecLossyLevel();
+
+ nxagentBackupDisplayInfo();
+
+ if (nxagentOption(Rootless))
+ {
+ nxagentFreePropertyList();
+ }
+
+ if (nxagentRenderEnable)
+ {
+ nxagentDisconnectAllPicture();
+ }
+
+ nxagentEmptyAllBackingStoreRegions();
+
+ nxagentDisconnectAllWindows();
+ nxagentDisconnectAllCursor();
+ nxagentDisconnectAllPixmaps();
+ nxagentDisconnectAllGCs();
+ nxagentDisconnectDisplay();
+
+ nxagentWMIsRunning = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectSession: Disconnection completed. SigHup is [%d]. IoError is [%d].\n",
+ nxagentException.sigHup, nxagentException.ioError);
+ #endif
+}
+
+Bool nxagentReconnectSession(void)
+{
+ char *nxagentOldKeyboard = NULL;
+
+ nxagentResizeDesktopAtStartup = False;
+
+ /*
+ * Propagate device settings if explicitly asked for.
+ */
+
+ nxagentChangeOption(DeviceControl, nxagentOption(DeviceControlUserDefined));
+
+ /*
+ * We need to zero out every new XID
+ * created by the disconnected display.
+ */
+
+ nxagentDisconnectSession();
+
+ /*
+ * Set this in order to let the screen
+ * function to behave differently at
+ * reconnection time.
+ */
+
+ nxagentReconnectTrap = True;
+
+ nxagentSetReconnectError(0, NULL);
+
+ if (nxagentKeyboard != NULL)
+ {
+ nxagentOldKeyboard = strndup(nxagentKeyboard, strlen(nxagentKeyboard));
+ if (nxagentOldKeyboard == NULL)
+ {
+ /* 0 means reconnection failed */
+ return 0;
+ }
+
+ free(nxagentKeyboard);
+ nxagentKeyboard = NULL;
+ }
+
+ nxagentSaveOptions();
+
+ nxagentResetOptions();
+
+ nxagentProcessOptionsFile();
+
+ if (nxagentReconnectDisplay(reconnectLossyLevel[DISPLAY_STEP]) == 0)
+ {
+ failedStep = DISPLAY_STEP;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnect: WARNING! Failed display reconnection.\n");
+ #endif
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectScreen(reconnectLossyLevel[SCREEN_STEP]) == 0)
+ {
+ failedStep = SCREEN_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ nxagentDisconnectAllFonts();
+
+ nxagentListRemoteFonts("*", nxagentMaxFontNames);
+
+ if (nxagentReconnectAllFonts(reconnectLossyLevel[FONT_STEP]) == 0)
+ {
+ if (nxagentReconnectFailedFonts(reconnectLossyLevel[FONT_STEP]) == 0)
+ {
+ failedStep = FONT_STEP;
+
+ goto nxagentReconnectError;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnect: WARNING! Unable to retrieve all the fonts currently in use. "
+ "Missing fonts have been replaced.\n");
+ #endif
+
+ nxagentLaunchDialog(DIALOG_FONT_REPLACEMENT);
+ }
+ }
+
+ /*
+ * Map the main window and send a
+ * SetSelectionOwner request to
+ * notify of the agent start.
+ */
+
+ nxagentMapDefaultWindows();
+
+ /*
+ * Ensure that the SetSelectionOwner
+ * request is sent through the link.
+ */
+
+ XFlush(nxagentDisplay);
+
+ NXTransContinue(NULL);
+
+ nxagentEmptyBSPixmapList();
+
+ if (nxagentReconnectAllPixmaps(reconnectLossyLevel[PIXMAP_STEP]) == 0)
+ {
+ failedStep = PIXMAP_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectAllGCs(reconnectLossyLevel[GC_STEP]) == 0)
+ {
+ failedStep = GC_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectAllColormap(reconnectLossyLevel[COLORMAP_STEP]) == 0)
+ {
+ failedStep = COLORMAP_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectAllWindows(reconnectLossyLevel[WINDOW_STEP]) == 0)
+ {
+ failedStep = WINDOW_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentRenderEnable)
+ {
+ if (nxagentReconnectAllGlyphSet(reconnectLossyLevel[GLYPHSET_STEP]) == 0)
+ {
+ failedStep = GLYPHSET_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectAllPictFormat(reconnectLossyLevel[PICTFORMAT_STEP]) == 0)
+ {
+ failedStep = PICTFORMAT_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentReconnectAllPicture(reconnectLossyLevel[PICTURE_STEP]) == 0)
+ {
+ failedStep = PICTURE_STEP;
+
+ goto nxagentReconnectError;
+ }
+ }
+
+ if (nxagentReconnectAllCursor(reconnectLossyLevel[CURSOR_STEP]) == 0)
+ {
+ failedStep = CURSOR_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentSetWindowCursors(reconnectLossyLevel[WINDOW_STEP]) == 0)
+ {
+ failedStep = WINDOW_STEP;
+
+ goto nxagentReconnectError;
+ }
+
+ if (nxagentOption(ResetKeyboardAtResume) == 1 &&
+ (nxagentKeyboard == NULL || nxagentOldKeyboard == NULL ||
+ strcmp(nxagentKeyboard, nxagentOldKeyboard) != 0 ||
+ strcmp(nxagentKeyboard, "query") == 0))
+ {
+ if (nxagentResetKeyboard() == 0)
+ {
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentReconnect: Failed to reset keyboard device.\n");
+ }
+ #endif
+
+ failedStep = WINDOW_STEP;
+
+ goto nxagentReconnectError;
+ }
+ }
+ else
+ {
+ nxagentResetKeycodeConversion();
+ }
+
+ nxagentXkbState.Initialized = 0;
+
+ if (nxagentOldKeyboard != NULL)
+ {
+ free(nxagentOldKeyboard);
+
+ nxagentOldKeyboard = NULL;
+ }
+
+ nxagentInitPointerMap();
+
+ nxagentDeactivatePointerGrab();
+
+ nxagentWakeupByReconnect();
+
+ nxagentFreeGCList();
+
+ nxagentRedirectDefaultWindows();
+
+ if (nxagentResizeDesktopAtStartup || nxagentOption(Rootless) == True || nxagentOption(Xinerama) == True)
+ {
+ nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight), 0, 0);
+
+ nxagentResizeDesktopAtStartup = False;
+ }
+
+ nxagentReconnectTrap = False;
+
+ nxagentExposeArrayIsInitialized = False;
+
+ if (nxagentSessionState != SESSION_GOING_UP)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnect: WARNING! Unexpected session state [%s] while reconnecting.\n",
+ DECODE_SESSION_STATE(nxagentSessionState));
+ #endif
+
+ goto nxagentReconnectError;
+ }
+
+ /* Re-read keystrokes definitions in case the keystrokes file has
+ changed while being supended */
+ nxagentInitKeystrokes(True);
+
+ #ifdef NX_DEBUG_INPUT
+ fprintf(stderr, "Session: Session resumed at '%s' timestamp [%lu].\n", GetTimeAsString(), GetTimeInMillis());
+ #else
+ fprintf(stderr, "Session: Session resumed at '%s'.\n", GetTimeAsString());
+ #endif
+ saveAgentState("RUNNING");
+
+ nxagentRemoveSplashWindow(NULL);
+
+ /*
+ * We let the proxy flush the link on our behalf
+ * after having opened the display. We are now
+ * entering again the dispatcher so can flush
+ * the link explicitly.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnect: Setting the NX flush policy to deferred.\n");
+ #endif
+
+ NXSetDisplayPolicy(nxagentDisplay, NXPolicyDeferred);
+
+ nxagentCleanupBackupDisplayInfo();
+
+ return 1;
+
+nxagentReconnectError:
+
+ if (failedStep == DISPLAY_STEP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnect: Reconnection failed in display step. Restoring options.\n");
+ #endif
+
+ nxagentRestoreOptions();
+ }
+ else
+ {
+ nxagentCleanupBackupDisplayInfo();
+ }
+
+ if (*nxagentGetReconnectError() == '\0')
+ {
+ #ifdef WARNING
+ if (nxagentVerbose == 1)
+ {
+ fprintf(stderr, "nxagentReconnect: WARNING! The reconnect error message is not set. Failed step is [%d].\n",
+ failedStep);
+ }
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnect: Reconnection failed due to a display error.\n");
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnect: Reconnection failed with reason '%s'\n",
+ nxagentGetReconnectError());
+ #endif
+ }
+
+ if (NXDisplayError(nxagentDisplay) == 0)
+ {
+ nxagentUnmapWindows();
+
+ nxagentFailedReconnectionDialog(nxagentReconnectErrorId, nxagentGetReconnectError());
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentReconnect: Cannot launch the dialog without a valid display.\n");
+ }
+ #endif
+
+ if (failedStep == FONT_STEP)
+ {
+ *((int *) reconnectLossyLevel[FONT_STEP]) = 1;
+ }
+
+ if (nxagentDisplay == NULL)
+ {
+ nxagentDisconnectDisplay();
+ }
+
+ if (nxagentOldKeyboard != NULL)
+ {
+ free(nxagentOldKeyboard);
+
+ nxagentOldKeyboard = NULL;
+ }
+
+ return 0;
+}
+
+void nxagentSetReconnectError(int id, char *format, ...)
+{
+ static int size = 0;
+
+ va_list ap;
+ int n;
+
+ if (format == NULL)
+ {
+ nxagentSetReconnectError(id, "");
+
+ return;
+ }
+
+ nxagentReconnectErrorId = id;
+
+ while (1)
+ {
+ va_start (ap, format);
+
+ n = vsnprintf(nxagentReconnectErrorMessage, size, format, ap);
+
+ va_end(ap);
+
+ if (n > -1 && n < size)
+ {
+ break;
+ }
+ if (n > -1)
+ {
+ size = n + 1;
+ }
+ else
+ {
+ /*
+ * The vsnprintf() in glibc 2.0.6 would return
+ * -1 when the output was truncated. See section
+ * NOTES on printf(3).
+ */
+
+ size = (size ? size * 2 : NXAGENT_RECONNECT_DEFAULT_MESSAGE_SIZE);
+ }
+
+ nxagentReconnectErrorMessage = realloc(nxagentReconnectErrorMessage, size);
+
+ if (nxagentReconnectErrorMessage == NULL)
+ {
+ FatalError("realloc failed");
+ }
+ }
+
+ return;
+}
+
+static char* nxagentGetReconnectError()
+{
+ if (nxagentReconnectErrorMessage == NULL)
+ {
+ nxagentSetReconnectError(nxagentReconnectErrorId, "");
+ }
+
+ return nxagentReconnectErrorMessage;
+}
+
+void nxagentHandleConnectionChanges()
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleConnectionChanges: Called.\n");
+ #endif
+
+ if (nxagentSessionState == SESSION_GOING_DOWN)
+ {
+ fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString());
+ saveAgentState("SUSPENDING");
+
+ nxagentDisconnectSession();
+ }
+ else if (nxagentSessionState == SESSION_GOING_UP)
+ {
+ fprintf(stderr, "Session: Resuming session at '%s'.\n", GetTimeAsString());
+ saveAgentState("RESUMING");
+
+ if (nxagentReconnectSession())
+ {
+ nxagentSessionState = SESSION_UP;
+ }
+ else
+ {
+ nxagentSessionState = SESSION_GOING_DOWN;
+
+ fprintf(stderr, "Session: Display failure detected at '%s'.\n", GetTimeAsString());
+
+ fprintf(stderr, "Session: Suspending session at '%s'.\n", GetTimeAsString());
+ saveAgentState("SUSPENDING");
+
+ nxagentDisconnectSession();
+ }
+ }
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h
new file mode 100644
index 000000000..d1c62166b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Reconnect.h
@@ -0,0 +1,78 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Reconnect_H__
+#define __Reconnect_H__
+
+extern Display *nxagentDisplayState;
+
+struct nxagentExceptionStruct
+{
+ int sigHup;
+ int ioError;
+};
+
+extern struct nxagentExceptionStruct nxagentException;
+
+void nxagentSetReconnectError(int id, char *format, ...);
+
+void nxagentInitReconnector(void);
+Bool nxagentReconnectSession(void);
+int nxagentHandleConnectionStates(void);
+void nxagentHandleConnectionChanges(void);
+void setStatePath(char*);
+void saveAgentState(char*);
+
+enum SESSION_STATE
+{
+ SESSION_STARTING,
+ SESSION_UP,
+ SESSION_DOWN,
+ SESSION_GOING_DOWN,
+ SESSION_GOING_UP
+};
+
+extern enum SESSION_STATE nxagentSessionState;
+
+#define DECODE_SESSION_STATE(state) \
+ ((state) == SESSION_STARTING ? "SESSION_STARTING" : \
+ (state) == SESSION_UP ? "SESSION_UP" : \
+ (state) == SESSION_GOING_UP? "SESSION_GOING_UP" : \
+ (state) == SESSION_DOWN ? "SESSION_DOWN" : \
+ (state) == SESSION_GOING_DOWN? "SESSION_GOING_DOWN" : \
+ "UNKNOWN")
+
+/*
+ * Use this macro in the block and wakeup
+ * handlers to save a function call.
+ */
+
+#define nxagentNeedConnectionChange() \
+ (nxagentSessionState == SESSION_GOING_DOWN || \
+ nxagentSessionState == SESSION_GOING_UP)
+
+void nxagentDisconnectSession(void);
+
+#endif /* __Reconnect_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Render.c b/nx-X11/programs/Xserver/hw/nxagent/Render.c
new file mode 100644
index 000000000..753134eb3
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Render.c
@@ -0,0 +1,3047 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "picturestr.h"
+#include "glyphstr.h"
+
+#include "Render.h"
+
+#include "X.h"
+#include "Xproto.h"
+
+#include "render.h"
+#include "renderproto.h"
+
+#include "mi.h"
+#include "fb.h"
+#include "mipict.h"
+#include "fbpict.h"
+#include "dixstruct.h"
+#include "protocol-versions.h"
+
+#include "Agent.h"
+#include "Drawable.h"
+#include "Trap.h"
+#include "Args.h"
+
+#define Atom XlibAtom
+#define Pixmap XlibPixmap
+#include "X11/include/Xrenderint_nxagent.h"
+#undef Atom
+#undef Pixmap
+
+#include "region.h"
+#include <X11/extensions/extutil.h>
+
+#include "Display.h"
+#include "Pixmaps.h"
+#include "Cursor.h"
+#include "Client.h"
+#include "Image.h"
+#include "Pixels.h"
+#include "Handlers.h"
+
+#include <nx/NXproto.h>
+
+#define MAX_FORMATS 255
+
+#define NXAGENT_PICTURE_ALWAYS_POINTS_TO_VIRTUAL
+
+/*
+ * Define if you want split multiple glyph lists
+ * into multiple RenderCompositeGlyphs requests.
+ */
+
+#undef SPLIT_GLYPH_LISTS
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+FIXME: Most operations don't seem to produce any visible result
+ but still generate tons of traffic.
+*/
+#undef SKIP_LOUSY_RENDER_OPERATIONS
+#undef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS
+
+/*
+ * Do we split the big trapezoid requests?
+ */
+
+#define TRAPEZOIDS_PER_REQUEST 256
+
+/*
+ * Margin added around the glyphs extent (in pixels).
+ */
+
+#define GLYPH_BOX_MARGIN 2
+
+int nxagentRenderEnable = UNDEFINED;
+int nxagentRenderVersionMajor;
+int nxagentRenderVersionMinor;
+
+int nxagentPicturePrivateIndex = 0;
+
+static int nxagentNumFormats = 0;
+
+static XRenderPictFormat nxagentArrayFormats[MAX_FORMATS];
+
+XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pForm);
+
+BoxPtr nxagentGlyphsExtents;
+BoxPtr nxagentTrapezoidExtents;
+
+#ifdef DEBUG
+
+static void nxagentPrintFormat(XRenderPictFormat *pFormat);
+
+#endif
+
+/*
+ * From NXglyph.c.
+ */
+
+extern const CARD8 glyphDepths[];
+
+/*
+ * From BitmapUtils.c.
+ */
+
+extern void nxagentBitOrderInvert(unsigned char *data, int nbytes);
+
+/*
+ * Other functions defined here.
+ */
+
+void nxagentQueryFormats(void);
+
+void nxagentCreateGlyphSet(GlyphSetPtr pGly);
+
+int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor);
+
+void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen,
+ PicturePtr pPicture, int x, int y);
+
+int nxagentCreatePicture(PicturePtr pPicture, Mask mask);
+
+int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects,
+ xRectangle *rects, int xOrigin, int yOrigin);
+
+void nxagentDestroyPictureClip(PicturePtr pPicture);
+
+void nxagentValidatePicture(PicturePtr pPicture, Mask mask);
+
+void nxagentComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height);
+
+void nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
+ XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase);
+
+void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color,
+ int nRect, xRectangle *rects);
+
+void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps);
+
+void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap,
+ int x_off, int y_off);
+
+void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris);
+
+void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points);
+
+void nxagentChangePicture(PicturePtr pPicture, Mask mask);
+
+void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points);
+
+void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet);
+
+void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph);
+
+void nxagentFreeGlyphSet(GlyphSetPtr glyphSet);
+
+void nxagentSetPictureTransform(PicturePtr pPicture, void * transform);
+
+void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
+ void * params, int nparams);
+
+Bool nxagentReconnectAllGlyphSet(void *p);
+
+Bool nxagentReconnectAllPicture(void *);
+
+Bool nxagentDisconnectAllPicture(void);
+
+void nxagentRenderExtensionInit()
+{
+ int first_event, first_error;
+ int major_version, minor_version;
+
+ if (XRenderQueryExtension(nxagentDisplay, &first_event, &first_error))
+ {
+ XRenderQueryVersion(nxagentDisplay, &major_version, &minor_version);
+
+ /*
+ * As the RENDER requests are passed directly to
+ * the remote X server this can cause problems if
+ * our RENDER version is different from the version
+ * supported by the remote. For this reasos let's
+ * advertise to our clients the lowest between the
+ + two versions.
+ */
+
+ if (major_version > SERVER_RENDER_MAJOR_VERSION ||
+ (major_version == SERVER_RENDER_MAJOR_VERSION &&
+ minor_version > SERVER_RENDER_MINOR_VERSION))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderExtensionInit: Using render version [%d.%d] with "
+ "remote version [%d.%d].\n", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
+ major_version, minor_version);
+ #endif
+
+ nxagentRenderVersionMajor = SERVER_RENDER_MAJOR_VERSION;
+ nxagentRenderVersionMinor = SERVER_RENDER_MINOR_VERSION;
+ }
+ else if (major_version < SERVER_RENDER_MAJOR_VERSION ||
+ (major_version == SERVER_RENDER_MAJOR_VERSION &&
+ minor_version < SERVER_RENDER_MINOR_VERSION))
+ {
+ #ifdef TEST
+ fprintf(stderr, "Info: Local render version %d.%d is higher "
+ "than remote version %d.%d.\n", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
+ major_version, minor_version);
+
+ fprintf(stderr, "Info: Lowering the render version reported to clients.\n");
+ #endif
+
+ nxagentRenderVersionMajor = major_version;
+ nxagentRenderVersionMinor = minor_version;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderExtensionInit: Local render version %d.%d "
+ "matches remote version %d.%d.\n", SERVER_RENDER_MAJOR_VERSION, SERVER_RENDER_MINOR_VERSION,
+ major_version, minor_version);
+ #endif
+
+ nxagentRenderVersionMajor = major_version;
+ nxagentRenderVersionMinor = minor_version;
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Render not available on the remote display.\n");
+ #endif
+
+ nxagentRenderEnable = False;
+ }
+}
+
+int nxagentCursorSaveRenderInfo(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ pCursor -> devPriv[pScreen -> myNum] = malloc(sizeof(nxagentPrivCursor));
+
+ if (nxagentCursorPriv(pCursor, pScreen) == NULL)
+ {
+ FatalError("malloc failed");
+ }
+
+ nxagentCursorUsesRender(pCursor, pScreen) = 1;
+ nxagentCursorPicture(pCursor, pScreen) = NULL;
+
+ return 1;
+}
+
+void nxagentCursorPostSaveRenderInfo(CursorPtr pCursor, ScreenPtr pScreen,
+ PicturePtr pPicture, int x, int y)
+{
+ nxagentCursorPicture(pCursor, pScreen) = pPicture;
+ nxagentCursorXOffset(pCursor, pScreen) = x;
+ nxagentCursorYOffset(pCursor, pScreen) = y;
+}
+
+int nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
+{
+ int cid;
+ int x, y;
+
+ PicturePtr pPicture;
+
+ pPicture = nxagentCursorPicture(pCursor, pScreen);
+
+ pPicture -> refcnt++;
+
+ x = nxagentCursorXOffset(pCursor, pScreen);
+ y = nxagentCursorYOffset(pCursor, pScreen);
+
+ /*
+ * Set the lossless trap so that the image functions
+ * will not try to encode the image using a lossy
+ * compression. Drawables should have a quality flag,
+ * telling if they were originally encoded with a
+ * lossy algorithm. This would allow us to skip the
+ * synchronization if the cursor was already encoded
+ * with the best quality.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderRealizeCursor: Forcing the synchronization "
+ "of the cursor.\n");
+ #endif
+
+ nxagentMarkCorruptedRegion(pPicture -> pDrawable, NULL);
+
+ nxagentLosslessTrap = 1;
+
+ nxagentSynchronizeDrawable(pPicture -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+
+ nxagentLosslessTrap = 0;
+
+ cid = XRenderCreateCursor(nxagentDisplay, nxagentPicture(pPicture), x, y);
+
+ nxagentCursor(pCursor, pScreen) = cid;
+
+ return 1;
+}
+
+int nxagentCreatePicture(PicturePtr pPicture, Mask mask)
+{
+ XRenderPictureAttributes attributes;
+ unsigned long valuemask=0;
+ XRenderPictFormat *pForm;
+
+ Picture id;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreatePicture: Function called with picture at [%p] and mask [%ld].\n",
+ (void *) pPicture, mask);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return 0;
+ }
+
+ #ifdef DEBUG
+
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ if (nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable))
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a shared pixmap.\n");
+ }
+ else
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a plain pixmap.\n");
+ }
+ }
+ else
+ {
+ fprintf (stderr, "nxagentCreatePicture: Picture uses a window.\n");
+ }
+
+ #endif
+
+ /*
+ * All the picture default values are 0.
+ */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0, sizeof(XRenderPictureAttributes));
+
+ if (mask & CPRepeat)
+ {
+ attributes.repeat = (Bool)pPicture -> repeat;
+
+ valuemask |= CPRepeat;
+
+ nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat);
+ }
+
+ if (mask & CPAlphaMap)
+ {
+ attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture;
+
+ valuemask |= CPAlphaMap;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map);
+ }
+
+ if (mask & CPAlphaXOrigin)
+ {
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+
+ valuemask |= CPAlphaXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin);
+ }
+
+ if (mask & CPAlphaYOrigin)
+ {
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ valuemask |= CPAlphaYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin);
+ }
+
+ if (mask & CPClipXOrigin)
+ {
+ attributes.clip_x_origin = pPicture -> clipOrigin.x;
+
+ valuemask |= CPClipXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin);
+ }
+
+ if (mask & CPClipYOrigin)
+ {
+ attributes.clip_y_origin = pPicture -> clipOrigin.y;
+
+ valuemask |= CPClipYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin);
+ }
+
+ if (mask & CPGraphicsExposure)
+ {
+ attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures;
+
+ valuemask |= CPGraphicsExposure;
+
+ nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures);
+ }
+
+ if (mask & CPSubwindowMode)
+ {
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ valuemask |= CPSubwindowMode;
+
+ nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode);
+ }
+
+ if (mask & CPClipMask)
+ {
+ attributes.clip_mask = None;
+
+ valuemask |= CPClipMask;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, attributes.clip_mask);
+ }
+
+ if (mask & CPPolyEdge)
+ {
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ valuemask |= CPPolyEdge;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge);
+ }
+
+ if (mask & CPPolyMode)
+ {
+ attributes.poly_mode = pPicture -> polyMode;
+
+ valuemask |= CPPolyMode;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode);
+ }
+
+ if (mask & CPDither)
+ {
+ attributes.dither = pPicture -> dither;
+
+ valuemask |= CPDither;
+
+ nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither);
+ }
+
+ if (mask & CPComponentAlpha)
+ {
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ valuemask |= CPComponentAlpha;
+
+ nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha);
+ }
+
+ pForm = NULL;
+
+ if (pPicture -> pFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(pPicture -> pFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+ }
+
+ if (pForm == NULL)
+ {
+ fprintf(stderr, "nxagentCreatePicture: WARNING! The requested format was not found.\n");
+
+ return 0;
+ }
+
+ id = XRenderCreatePicture(nxagentDisplay,
+ nxagentDrawable(pPicture -> pDrawable),
+ pForm,
+ valuemask,
+ &attributes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreatePicture: Created picture at [%p] with drawable at [%p].\n",
+ (void *) pPicture, (void *) pPicture -> pDrawable);
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+
+ if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable->depth == 32 &&
+ pPicture -> pFormat -> direct.alpha != 0)
+ {
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pPicture -> pDrawable)) -> pPicture = pPicture;
+ }
+ else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ }
+
+ return 1;
+}
+
+XRenderPictFormat *nxagentMatchingFormats(PictFormatPtr pFormat)
+{
+ int i;
+
+ for (i = 0; i < nxagentNumFormats; i++)
+ {
+ if (pFormat -> type == nxagentArrayFormats[i].type &&
+ pFormat -> depth == nxagentArrayFormats[i].depth &&
+ pFormat -> direct.red == nxagentArrayFormats[i].direct.red &&
+ pFormat -> direct.green == nxagentArrayFormats[i].direct.green &&
+ pFormat -> direct.blue == nxagentArrayFormats[i].direct.blue &&
+ pFormat -> direct.redMask == nxagentArrayFormats[i].direct.redMask &&
+ pFormat -> direct.greenMask == nxagentArrayFormats[i].direct.greenMask &&
+ pFormat -> direct.blueMask == nxagentArrayFormats[i].direct.blueMask &&
+ pFormat -> direct.alpha == nxagentArrayFormats[i].direct.alpha &&
+ pFormat -> direct.alphaMask == nxagentArrayFormats[i].direct.alphaMask)
+ {
+ return &nxagentArrayFormats[i];
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMatchingFormats: The requested format was not found.\n");
+ #endif
+
+ return NULL;
+}
+
+void nxagentDestroyPicture(PicturePtr pPicture)
+{
+ if (pPicture == NULL || nxagentPicturePriv(pPicture) -> picture == 0)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyPicture: Going to destroy picture at [%p].\n",
+ (void *) pPicture);
+ #endif
+
+ XRenderFreePicture(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+int nxagentChangePictureClip(PicturePtr pPicture, int clipType, int nRects,
+ xRectangle *rects, int xOrigin, int yOrigin)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangePictureClip: Going to change clip of picture at [%p].\n",
+ (void *) pPicture);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: clipType [%d] nRects [%d] xRectangle [%p] "
+ "xOrigin [%d] yOrigin [%d].\n", clipType, nRects, (void *) rects, xOrigin, yOrigin);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return 0;
+ }
+
+ switch (clipType)
+ {
+ case CT_PIXMAP:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_PIXMAP].\n");
+ #endif
+
+ /*
+ * if(!nRects)
+ * {
+ * return 0;
+ * }
+ */
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRectangles(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ xOrigin,
+ yOrigin,
+ (XRectangle*)rects,
+ nRects);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ break;
+ }
+ case CT_NONE:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_NONE].\n");
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRectangles(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ xOrigin,
+ yOrigin,
+ (XRectangle*)rects,
+ nRects);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ break;
+ }
+ case CT_REGION:
+ {
+ Region reg;
+ XRectangle rectangle;
+ int index;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: Clip type is [CT_REGION].\n");
+ #endif
+
+ reg = XCreateRegion();
+
+ for (index = 0; index <= nRects; index++, rects++)
+ {
+ rectangle.x = rects -> x;
+ rectangle.y = rects -> y;
+ rectangle.width = rects -> width;
+ rectangle.height = rects -> height;
+
+ XUnionRectWithRegion(&rectangle, reg, reg);
+ }
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureClipRegion(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ reg);
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, xOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, yOrigin);
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 1);
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ XDestroyRegion(reg);
+
+ break;
+ }
+ default:
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePictureClip: clipType not found\n");
+ #endif
+
+ break;
+ }
+ }
+
+ return 1;
+}
+
+void nxagentDestroyPictureClip(PicturePtr pPicture)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDestroyPictureClip: Nothing to do.\n");
+ #endif
+}
+
+void nxagentChangePicture(PicturePtr pPicture, Mask mask)
+{
+ XRenderPictureAttributes attributes;
+ unsigned long valuemask = 0;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangePicture: Going to change picture at [%p] with mask [%ld].\n",
+ (void *) pPicture, mask);
+ #endif
+
+ if (pPicture == NULL)
+ {
+ return;
+ }
+
+ if (mask & CPRepeat)
+ {
+ attributes.repeat = (Bool)pPicture -> repeat;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, repeat, attributes.repeat) == 0)
+ {
+ valuemask |= CPRepeat;
+
+ nxagentSetPictureRemoteValue(pPicture, repeat, attributes.repeat);
+ }
+ }
+
+ if (mask & CPAlphaMap)
+ {
+ attributes.alpha_map = nxagentPicturePriv(pPicture -> alphaMap) -> picture;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map) == 0)
+ {
+ valuemask |= CPAlphaMap;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_map, attributes.alpha_map);
+ }
+ }
+
+ if (mask & CPAlphaXOrigin)
+ {
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin) == 0)
+ {
+ valuemask |= CPAlphaXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_x_origin, attributes.alpha_x_origin);
+ }
+ }
+
+ if (mask & CPAlphaYOrigin)
+ {
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin) == 0)
+ {
+ valuemask |= CPAlphaYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, alpha_y_origin, attributes.alpha_y_origin);
+ }
+ }
+
+ if (mask & CPClipXOrigin)
+ {
+ attributes.clip_x_origin = pPicture -> clipOrigin.x;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin) == 0)
+ {
+ valuemask |= CPClipXOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_x_origin, attributes.clip_x_origin);
+ }
+ }
+
+ if (mask & CPClipYOrigin)
+ {
+ attributes.clip_y_origin = pPicture -> clipOrigin.y;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin) == 0)
+ {
+ valuemask |= CPClipYOrigin;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_y_origin, attributes.clip_y_origin);
+ }
+ }
+
+ if (mask & CPGraphicsExposure)
+ {
+ attributes.graphics_exposures = (Bool)pPicture -> graphicsExposures;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures) == 0)
+ {
+ valuemask |= CPGraphicsExposure;
+
+ nxagentSetPictureRemoteValue(pPicture, graphics_exposures, attributes.graphics_exposures);
+ }
+ }
+
+ if (mask & CPSubwindowMode)
+ {
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode) == 0)
+ {
+ valuemask |= CPSubwindowMode;
+
+ nxagentSetPictureRemoteValue(pPicture, subwindow_mode, attributes.subwindow_mode);
+ }
+ }
+
+ if (mask & CPClipMask)
+ {
+ attributes.clip_mask = None;
+
+ /*
+ * The nxagent doesn't know the remote id of
+ * the picture's clip mask, so the clip_mask
+ * value is used as a boolean: it is set to 0
+ * when the clip_mask is None, otherwise it is
+ * 1.
+ */
+
+ if (nxagentPicturePriv(pPicture) -> lastServerValues.clip_mask != 0)
+ {
+ valuemask |= CPClipMask;
+
+ nxagentSetPictureRemoteValue(pPicture, clip_mask, 0);
+ }
+ }
+
+ if (mask & CPPolyEdge)
+ {
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge) == 0)
+ {
+ valuemask |= CPPolyEdge;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_edge, attributes.poly_edge);
+ }
+ }
+
+ if (mask & CPPolyMode)
+ {
+ attributes.poly_mode = pPicture -> polyMode;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode) == 0)
+ {
+ valuemask |= CPPolyMode;
+
+ nxagentSetPictureRemoteValue(pPicture, poly_mode, attributes.poly_mode);
+ }
+ }
+
+ if (mask & CPDither)
+ {
+ attributes.dither = pPicture -> dither;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, dither, attributes.dither) == 0)
+ {
+ valuemask |= CPDither;
+
+ nxagentSetPictureRemoteValue(pPicture, dither, attributes.dither);
+ }
+ }
+
+ if (mask & CPComponentAlpha)
+ {
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ if (nxagentCheckPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha) == 0)
+ {
+ valuemask |= CPComponentAlpha;
+
+ nxagentSetPictureRemoteValue(pPicture, component_alpha, attributes.component_alpha);
+ }
+ }
+
+ #ifdef TEST
+
+ if (pPicture && pPicture->pDrawable && pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ fprintf(stderr, "nxagentChangePicture: %sPixmap [%p] Picture [%p][%p].\n",
+ nxagentIsShmPixmap((PixmapPtr)pPicture -> pDrawable) ? "Shared " : "",
+ (void *) pPicture -> pDrawable, (void *) nxagentPicturePriv(pPicture) -> picture,
+ (void *) pPicture);
+ }
+
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+
+ Without this the text is not rendered on GTK/Cairo.
+*/
+ #ifndef SKIP_REALLY_ALL_LOUSY_RENDER_OPERATIONS
+
+ if (valuemask != 0)
+ {
+ XRenderChangePicture(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ valuemask,
+ &attributes);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentChangePicture: Skipping change of picture [%p] on remote X server.\n",
+ (void *) pPicture);
+ }
+ #endif
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentValidatePicture(PicturePtr pPicture, Mask mask)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentValidatePicture: Nothing to do.\n");
+ #endif
+}
+
+void nxagentComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst,
+ INT16 yDst, CARD16 width, CARD16 height)
+{
+ RegionPtr pDstRegion;
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ if (pSrc && pSrc -> pDrawable != NULL)
+ {
+ fprintf(stderr, "nxagentComposite: Source Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pSrc) -> picture, (void *) pSrc,
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pSrc -> pDrawable)) ? "Shared " : "",
+ pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pSrc -> pDrawable);
+ }
+
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentComposite: Destination Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pDst) -> picture, (void *) pDst,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pDst -> pDrawable)) ? "Shared " : "",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pDst -> pDrawable);
+ }
+
+ if (pMask && pMask->pDrawable)
+ {
+ fprintf(stderr, "nxagentComposite: Mask Picture [%lu][%p] with drawable [%s%s][%p].\n",
+ nxagentPicturePriv(pMask) -> picture, (void *) pMask,
+ (pMask -> pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentIsShmPixmap((PixmapPtr) pMask -> pDrawable)) ? "Shared " : "",
+ pMask -> pDrawable -> type == DRAWABLE_PIXMAP ? "Pixmap" : "Window",
+ (void *) pMask -> pDrawable);
+ }
+
+ #endif
+
+ if (NXAGENT_SHOULD_DEFER_COMPOSITE(pSrc, pMask, pDst))
+ {
+ pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, xDst, yDst, width, height);
+
+ #ifdef TEST
+ if ((pDstRegion) && (pDst && pDst->pDrawable)) {
+ fprintf(stderr, "nxagentComposite: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable at [%p] with type [%s].\n", pDstRegion -> extents.x1,
+ pDstRegion -> extents.y1, pDstRegion -> extents.x2, pDstRegion -> extents.y2,
+ (void *) pDst -> pDrawable,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window");
+ }
+ #endif
+
+ nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDst -> pDrawable, pDstRegion);
+
+ return;
+ }
+
+ /*
+ * Synchronize the content of the shared memory pixmap
+ * but pay attention at not doing this more than once.
+ * We need to wait until the image data has been recom-
+ * posed at the X server side or the operation will use
+ * the wrong data.
+ */
+
+ if (pSrc -> pDrawable != NULL)
+ {
+ nxagentSynchronizeShmPixmap(pSrc -> pDrawable, xSrc, ySrc, width, height);
+
+ if (nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the source drawable [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ if (pDst -> pDrawable != pSrc -> pDrawable)
+ {
+ nxagentSynchronizeShmPixmap(pDst -> pDrawable, xDst, yDst, width, height);
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the destination drawable [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ if (pMask != NULL && pMask -> pDrawable != NULL &&
+ pMask -> pDrawable != pSrc -> pDrawable &&
+ pMask -> pDrawable != pDst -> pDrawable)
+ {
+ nxagentSynchronizeShmPixmap(pMask -> pDrawable, xMask, yMask, width, height);
+
+ if (nxagentDrawableStatus(pMask -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentComposite: Synchronizing the mask drawable [%p].\n",
+ (void *) pMask -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pMask -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+ }
+
+ /*
+ * The glyphs flag have to be propagated between
+ * drawables, in order to avoid to encode the
+ * text with lossy algorithms (like JPEG). Unlu-
+ * ckily we have verified that if the render com-
+ * posite propagates the flag, the deferring of
+ * render trapezoids doesn't work well. Moreover,
+ * by commenting out this code we have not noticed
+ * any visual problems.
+ *
+ * if (nxagentDrawableContainGlyphs(pSrc -> pDrawable) == 1)
+ * {
+ * nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1);
+ * }
+ */
+
+ XRenderComposite(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ pMask ? nxagentPicturePriv(pMask) -> picture : 0,
+ nxagentPicturePriv(pDst) -> picture,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlists,
+ XGlyphElt8 *elts, int sizeID, GlyphPtr *glyphsBase)
+{
+ XRenderPictFormat *pForm;
+
+ BoxRec glyphBox;
+
+ XGlyphElt8 *elements;
+
+ #ifdef SPLIT_GLYPH_LISTS
+
+ GlyphPtr glyph;
+
+ int x;
+ int y;
+ int i;
+ int j;
+
+ #endif /* #ifdef SPLIT_GLYPH_LISTS */
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ if ((pSrc && pSrc->pDrawable) && (pDst && pDst->pDrawable)) {
+ fprintf(stderr, "nxagentGlyphs: Called with source [%s][%p] destination [%s][%p] and size id [%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pSrc,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDst,
+ sizeID);
+ }
+ #endif
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ if (nxagentGlyphsExtents != NullBox)
+ {
+ glyphBox.x1 = nxagentGlyphsExtents -> x1;
+ glyphBox.y1 = nxagentGlyphsExtents -> y1;
+ glyphBox.x2 = nxagentGlyphsExtents -> x2;
+ glyphBox.y2 = nxagentGlyphsExtents -> y2;
+
+ /*
+ * By extending the glyph extents the
+ * visual aspect looks nicer because
+ * the synchronized region is not glued
+ * to the fonts.
+ */
+
+ if (glyphBox.x2 != glyphBox.x1)
+ {
+ glyphBox.x1 -= GLYPH_BOX_MARGIN;
+ glyphBox.x2 += GLYPH_BOX_MARGIN;
+ }
+
+ if (glyphBox.y2 != glyphBox.y1)
+ {
+ glyphBox.y1 -= GLYPH_BOX_MARGIN;
+ glyphBox.y2 += GLYPH_BOX_MARGIN;
+ }
+ }
+
+ /*
+ * If the destination window is hidden, the
+ * operation can be prevented.
+ */
+
+ if (pDst -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ RegionPtr pRegion;
+
+ pRegion = nxagentCreateRegion(pDst -> pDrawable, NULL, glyphBox.x1, glyphBox.y1,
+ glyphBox.x2 - glyphBox.x1, glyphBox.y2 - glyphBox.y1);
+
+ if (RegionNil(pRegion) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: WARNING! Glyphs prevented on hidden window at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentFreeRegion(pDst -> pDrawable, pRegion);
+
+ return;
+ }
+
+ nxagentFreeRegion(pDst -> pDrawable, pRegion);
+ }
+
+ /*
+ * Need to synchronize the pixmaps involved in
+ * the operation before rendering the glyphs
+ * on the real X server.
+ */
+
+ if (pSrc -> pDrawable != NULL &&
+ nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ if (pSrc && pSrc->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p].\n",
+ pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pSrc -> pDrawable);
+ }
+ #endif
+
+ /*
+ * If the source drawable is going to be
+ * repeated over the destination drawable
+ * during the composite operation, we need
+ * to synchronize the whole drawable to
+ * avoid graphical problems.
+ */
+
+ if (pSrc -> repeat == 1 || nxagentGlyphsExtents == NullBox)
+ {
+ #ifdef DEBUG
+ if (pSrc && pSrc->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing source [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y,
+ pSrc -> pDrawable -> x + pSrc -> pDrawable -> width,
+ pSrc -> pDrawable -> y + pSrc -> pDrawable -> height);
+ }
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK);
+ }
+ else
+ {
+ #ifdef DEBUG
+ if (pSrc && pSrc->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of source [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2,
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pSrc -> pDrawable, pSrc -> pDrawable -> x, pSrc -> pDrawable -> y,
+ pSrc -> pDrawable -> x + pSrc -> pDrawable -> width,
+ pSrc -> pDrawable -> y + pSrc -> pDrawable -> height);
+ }
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, &glyphBox, NEVER_BREAK);
+ }
+
+ if (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrc -> pDrawable);
+ }
+ }
+
+ if (pSrc -> pDrawable != pDst -> pDrawable &&
+ nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p].\n",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ }
+ #endif
+
+ if (nxagentGlyphsExtents == NullBox)
+ {
+ #ifdef DEBUG
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing destination [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n",
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y,
+ pDst -> pDrawable -> x + pDst -> pDrawable -> width,
+ pDst -> pDrawable -> y + pDst -> pDrawable -> height);
+ }
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, NullBox, NEVER_BREAK);
+ }
+ else
+ {
+ #ifdef DEBUG
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Synchronizing region [%d,%d,%d,%d] of destination [%s] at [%p] "
+ "with geometry [%d,%d,%d,%d].\n", glyphBox.x1, glyphBox.y1, glyphBox.x2, glyphBox.y2,
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable, pDst -> pDrawable -> x, pDst -> pDrawable -> y,
+ pDst -> pDrawable -> x + pDst -> pDrawable -> width,
+ pDst -> pDrawable -> y + pDst -> pDrawable -> height);
+ }
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, &glyphBox, NEVER_BREAK);
+ }
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentIncreasePixmapUsageCounter((PixmapPtr) pDst -> pDrawable);
+ }
+ }
+
+ nxagentSetDrawableContainGlyphs(pDst -> pDrawable, 1);
+
+ #ifdef TEST
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentGlyphs: Glyph flag set on drawable [%s][%p].\n",
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ }
+ #endif
+
+ #ifdef SPLIT_GLYPH_LISTS
+
+ /*
+ * We split glyphs lists here and recalculate
+ * the offsets of each list to make them ab-
+ * solute and not relatives to the prior list.
+ * This way each time we call XRenderComposi-
+ * teText it has to deal only with a list of
+ * glyphs. This is done to further improve
+ * caching.
+ */
+
+ elements = elts;
+
+ if (nlists > 1)
+ {
+ for (j = 1; j < nlists; j++)
+ {
+ x = elements -> xOff;
+ y = elements -> yOff;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Element [%d] of [%d] has offset [%d,%d].\n",
+ j, nlists, elements -> xOff, elements -> yOff);
+ #endif
+
+ for (i = 0; i < elements -> nchars; i++)
+ {
+ glyph = *glyphsBase++;
+
+ x += glyph -> info.xOff;
+ y += glyph -> info.yOff;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: Glyph at index [%d] has offset [%d,%d] and "
+ "position [%d,%d].\n", i, elements -> nchars, glyph -> info.xOff,
+ glyph -> info.yOff, x, y);
+ #endif
+ }
+
+ elements++;
+
+ elements -> xOff += x;
+ elements -> yOff += y;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentGlyphs: New offset for list at [%p] is [%d,%d].\n",
+ elements, elements -> xOff, elements -> yOff);
+ #endif
+ }
+
+ elements = elts;
+ }
+
+ switch (sizeID)
+ {
+ case 1:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText8(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc)->picture,
+ nxagentPicturePriv(pDst)->picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt8*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ case 2:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText16(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt16*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ case 4:
+ {
+ for (j = 0; j < nlists; j++)
+ {
+ XRenderCompositeText32(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt32*) elements,
+ 1);
+
+ elements++;
+ }
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n",
+ sizeID);
+ #endif
+
+ break;
+ }
+ }
+
+ #else /* #ifdef SPLIT_GLYPH_LISTS */
+
+ elements = elts;
+
+ switch (sizeID)
+ {
+ case 1:
+ {
+ XRenderCompositeText8(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc)->picture,
+ nxagentPicturePriv(pDst)->picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt8*) elements,
+ nlists);
+
+ break;
+ }
+ case 2:
+ {
+ XRenderCompositeText16(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt16*) elements,
+ nlists);
+
+ break;
+ }
+ case 4:
+ {
+ XRenderCompositeText32(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ elements -> xOff,
+ elements -> yOff,
+ (XGlyphElt32*) elements,
+ nlists);
+
+ break;
+ }
+ default:
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentGlyphs: WARNING! Invalid size id [%d].\n",
+ sizeID);
+ #endif
+
+ break;
+ }
+ }
+
+ #endif /* #ifdef SPLIT_GLYPH_LISTS */
+}
+
+void nxagentCompositeRects(CARD8 op, PicturePtr pDst, xRenderColor *color,
+ int nRect, xRectangle *rects)
+{
+ RegionPtr rectRegion;
+
+ if (pDst == NULL)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentCompositeRects: Called for picture at [%p] with [%s] at [%p].\n",
+ (void *) pDst, (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ (void *) pDst -> pDrawable);
+ }
+ #endif
+
+ /*
+ * The CompositeRects() clears the destination's
+ * corrupted region like the PolyFillRects() does.
+ * As this case is harder to handle, at the moment
+ * we only check for two ops.
+ */
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized &&
+ (op == PictOpSrc ||
+ (op == PictOpOver && color -> alpha == 0xffff)))
+ {
+ rectRegion = RegionFromRects(nRect, rects, CT_REGION);
+
+ if (pDst -> clientClipType != CT_NONE)
+ {
+ RegionRec tmpRegion;
+
+ RegionInit(&tmpRegion, NullBox, 1);
+
+ RegionCopy(&tmpRegion, (RegionPtr) pDst -> clientClip);
+
+ if (pDst -> clipOrigin.x != 0 || pDst -> clipOrigin.y != 0)
+ {
+ RegionTranslate(&tmpRegion, pDst -> clipOrigin.x, pDst -> clipOrigin.y);
+ }
+
+ RegionIntersect(rectRegion, rectRegion, &tmpRegion);
+
+ RegionUninit(&tmpRegion);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCompositeRects: Going to clean the drawable with extents [%d,%d,%d,%d].\n",
+ rectRegion -> extents.x1, rectRegion -> extents.y1, rectRegion -> extents.x2, rectRegion -> extents.y2);
+ #endif
+
+ nxagentUnmarkCorruptedRegion(pDst -> pDrawable, rectRegion);
+
+ RegionDestroy(rectRegion);
+ }
+
+ XRenderFillRectangles(nxagentDisplay,
+ op,
+ (Picture)nxagentPicturePriv(pDst) -> picture,
+ (XRenderColor *) color,
+ (XRectangle *) rects,
+ nRect);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ XRenderPictFormat *pForm;
+
+ XTrapezoid *current = (XTrapezoid *) traps;
+
+ RegionPtr pDstRegion;
+
+ int remaining = ntrap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Source [%p] destination [%p] coordinates "
+ "[%d,%d] elements [%d].\n", (void *) pSrc, (void *) pDst,
+ xSrc, ySrc, ntrap);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ #ifdef TEST
+
+ if (pSrc->pDrawable) {
+ fprintf(stderr, "nxagentTrapezoids: Source is a [%s] of geometry [%d,%d].\n",
+ (pSrc -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ pSrc -> pDrawable -> width, pSrc -> pDrawable -> height);
+ }
+ if (pSrc ->pDrawable != pDst -> pDrawable)
+ {
+ fprintf(stderr, "nxagentTrapezoids: Destination is a [%s] of geometry [%d,%d].\n",
+ (pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"),
+ pDst -> pDrawable -> width, pDst -> pDrawable -> height);
+ }
+
+ #endif
+
+ /*
+ * If the destination drawable is not synchronized
+ * but the trapezoids extents are included in the
+ * dirty region, we can defer the operation.
+ */
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized &&
+ RegionContainsRect(nxagentCorruptedRegion(pDst -> pDrawable),
+ nxagentTrapezoidExtents) == rgnIN)
+ {
+ #ifdef TEST
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] already dirty "
+ "for drawable [%s][%p].\n", nxagentTrapezoidExtents -> x1, nxagentTrapezoidExtents -> y1,
+ nxagentTrapezoidExtents -> x2, nxagentTrapezoidExtents -> y2,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ }
+ #endif
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1;
+ }
+
+ return;
+ }
+
+ /*
+ * If the destination doesn't contain any glyphs,
+ * we can defer the trapezoids drawing by marking
+ * the destination as dirty.
+ */
+
+ if (NXAGENT_SHOULD_DEFER_TRAPEZOIDS(pDst -> pDrawable))
+ {
+ pDstRegion = nxagentCreateRegion(pDst -> pDrawable, NULL,
+ nxagentTrapezoidExtents -> x1,
+ nxagentTrapezoidExtents -> y1,
+ nxagentTrapezoidExtents -> x2 - nxagentTrapezoidExtents -> x1,
+ nxagentTrapezoidExtents -> y2 - nxagentTrapezoidExtents -> y1);
+
+ #ifdef TEST
+ if (pDst && pDst->pDrawable) {
+ fprintf(stderr, "nxagentTrapezoids: WARNING! Prevented operation on region [%d,%d,%d,%d] "
+ "for drawable [%s][%p].\n", pDstRegion -> extents.x1, pDstRegion -> extents.y1,
+ pDstRegion -> extents.x2, pDstRegion -> extents.y2,
+ pDst -> pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window",
+ (void *) pDst -> pDrawable);
+ }
+ #endif
+
+ nxagentMarkCorruptedRegion(pDst -> pDrawable, pDstRegion);
+
+ nxagentFreeRegion(pDst -> pDrawable, pDstRegion);
+
+ if (pDst -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapContainTrapezoids((PixmapPtr) pDst -> pDrawable) = 1;
+ }
+
+ return;
+ }
+
+ if (pSrc -> pDrawable != NULL &&
+ nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeBox(pSrc -> pDrawable, NullBox, NEVER_BREAK);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTrapezoids: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeBox(pDst -> pDrawable, nxagentTrapezoidExtents, NEVER_BREAK);
+ }
+
+ while (remaining > 0)
+ {
+ XRenderCompositeTrapezoids(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XTrapezoid *) current,
+ (remaining > TRAPEZOIDS_PER_REQUEST ?
+ TRAPEZOIDS_PER_REQUEST : remaining));
+
+ remaining -= TRAPEZOIDS_PER_REQUEST;
+ current += TRAPEZOIDS_PER_REQUEST;
+ }
+
+ #endif
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentRasterizeTrapezoid(PicturePtr pMask, xTrapezoid *trap,
+ int x_off, int y_off)
+{
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentRasterizeTrapezoids: Nothing to do.\n");
+ #endif
+}
+
+void nxagentTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriangles: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, ntri);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriangles requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (pSrc -> pDrawable != NULL &&
+ nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriangles: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriangles: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriangles(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XTriangle*)tris,
+ ntri);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriStrip: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriStrip requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (pSrc -> pDrawable != NULL &&
+ nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriStrip: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriStrip: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriStrip(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XPointFixed*)points,
+ npoint);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentTriFan: Source [%p] Destination [%p] Coordinates [%d,%d] Elements [%d].\n",
+ (void *) pSrc, (void *) pDst, xSrc, ySrc, npoint);
+ #endif
+
+ if (pSrc == NULL || pDst == NULL)
+ {
+ return;
+ }
+
+ pForm = NULL;
+
+ if (maskFormat != NULL)
+ {
+ pForm = nxagentMatchingFormats(maskFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ /*
+ * If the X_RenderCompositeTriFan requests
+ * increment the traffic, we can defer the
+ * operation like nxagentTrapezoids() does.
+ */
+
+ if (pSrc -> pDrawable != NULL &&
+ nxagentDrawableStatus(pSrc -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriFan: Going to synchronize the source drawable at [%p].\n",
+ (void *) pSrc -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pSrc -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ if (nxagentDrawableStatus(pDst -> pDrawable) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentTriFan: Going to synchronize the destination drawable at [%p].\n",
+ (void *) pDst -> pDrawable);
+ #endif
+
+ nxagentSynchronizeDrawable(pDst -> pDrawable, DO_WAIT, NEVER_BREAK, NULL);
+ }
+
+ XRenderCompositeTriFan(nxagentDisplay,
+ op,
+ nxagentPicturePriv(pSrc) -> picture,
+ nxagentPicturePriv(pDst) -> picture,
+ pForm,
+ xSrc,
+ ySrc,
+ (XPointFixed*)points,
+ npoint);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentQueryFormats()
+{
+ XRenderInfo *xri;
+ XExtDisplayInfo *info = NULL;
+ XRenderPictFormat *pformat=NULL;
+
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentQueryFormats.\n");
+ #endif
+
+ if (XRenderQueryFormats(nxagentDisplay))
+ {
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ info = (XExtDisplayInfo *) XRenderFindDisplay(nxagentDisplay);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ xri = (XRenderInfo *) info -> data;
+
+ pformat = xri -> format;
+
+ for (i = 0; i < xri -> nformat; i++)
+ {
+ nxagentArrayFormats[i] = *pformat;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentQueryFormats: Added format type [%d] depth [%d] rgb [%d,%d,%d] "
+ "mask rgb [%d,%d,%d] alpha [%d] alpha mask [%d].\n",
+ nxagentArrayFormats[i].type, nxagentArrayFormats[i].depth, nxagentArrayFormats[i].direct.red,
+ nxagentArrayFormats[i].direct.green, nxagentArrayFormats[i].direct.blue,
+ nxagentArrayFormats[i].direct.redMask, nxagentArrayFormats[i].direct.greenMask,
+ nxagentArrayFormats[i].direct.blueMask, nxagentArrayFormats[i].direct.alpha,
+ nxagentArrayFormats[i].direct.alphaMask);
+ #endif
+
+ pformat++;
+ }
+
+ #ifdef DEBUG
+
+ if (nxagentNumFormats == 0)
+ {
+ fprintf(stderr, "nxagentQueryFormats: Number of formats is [%d].\n",
+ i);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentQueryFormats: Old number of formats is [%d]. New number of formats is [%d].\n",
+ nxagentNumFormats, i);
+ }
+
+ #endif
+
+ nxagentNumFormats = i;
+ }
+}
+
+void nxagentCreateGlyphSet(GlyphSetPtr pGly)
+{
+ XRenderPictFormat *pForm;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentCreateGlyphSet: Glyphset at [%p].\n", (void *) pGly);
+ #endif
+
+ pForm = NULL;
+
+ if (pGly -> format != NULL)
+ {
+ pForm = nxagentMatchingFormats(pGly -> format);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+
+ if (pForm == NULL)
+ {
+ return;
+ }
+ }
+
+ pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm);
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentReferenceGlyphSet(GlyphSetPtr glyphSet)
+{
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReferenceGlyphSet: Operation deferred because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ XRenderReferenceGlyphSet (nxagentDisplay, glyphSet -> remoteID);
+}
+
+void nxagentFreeGlyphSet(GlyphSetPtr glyphSet)
+{
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ XRenderFreeGlyphSet(nxagentDisplay, glyphSet -> remoteID);
+}
+
+void nxagentAddGlyphs(GlyphSetPtr glyphSet, Glyph *gids, xGlyphInfo *gi,
+ int nglyphs, CARD8 *images, int sizeImages)
+{
+ GlyphRefPtr gr;
+ Glyph *tempGids;
+
+ int i;
+
+ CARD8 *normalizedImages;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAddGlyphs: Glyphset at [%p]. Number of glyphs [%d].\n",
+ (void *) glyphSet, nglyphs);
+ #endif
+
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddGlyphs: Going to reconnect the glyhpset at [%p] before adding glyphs.\n",
+ (void *) glyphSet);
+ #endif
+
+ nxagentReconnectGlyphSet(glyphSet, (XID) 0, (void*) NULL);
+ }
+
+ /*
+ * By adding a glyph to a glyphset on
+ * remote X server we mark its reference
+ * as synchronized.
+ */
+
+ tempGids = gids;
+
+ for (i = 0; i < nglyphs; i++)
+ {
+ if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) &&
+ gr -> glyph != DeletedGlyph)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAddGlyphs: Added Glyph [%p][%ld] to glyphset [%p].\n",
+ (void *) gr -> glyph, *tempGids, (void *) glyphSet);
+ #endif
+
+ gr -> corruptedGlyph = 0;
+ }
+
+ tempGids++;
+ }
+
+ normalizedImages = NULL;
+
+ if (sizeImages > 0)
+ {
+ normalizedImages = malloc(sizeImages);
+
+ if (normalizedImages != NULL)
+ {
+ memcpy(normalizedImages, images, sizeImages);
+
+ if (glyphDepths[glyphSet -> fdepth] == 1 &&
+ nxagentServerOrder() != BitmapBitOrder(nxagentDisplay))
+ {
+ nxagentBitOrderInvert ((unsigned char *) normalizedImages, sizeImages);
+ }
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentAddGlyphs: PANIC! Allocation of normalized glyph images failed.\n");
+ #endif
+ }
+ }
+
+ if (normalizedImages == NULL)
+ {
+ normalizedImages = images;
+ }
+
+ XRenderAddGlyphs(nxagentDisplay,
+ glyphSet -> remoteID,
+ gids,
+ (XGlyphInfo*)(gi),
+ nglyphs,
+ (char*) normalizedImages,
+ sizeImages);
+
+ if (normalizedImages != images)
+ {
+ free(normalizedImages);
+ }
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+}
+
+void nxagentFreeGlyphs(GlyphSetPtr glyphSet, CARD32 *gids, int nglyph)
+{
+ GlyphRefPtr gr;
+ CARD32 *tempGids;
+ Glyph gid;
+
+ int i;
+
+ if (glyphSet -> remoteID == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeGlyphs: Operation ignored because glyphset at [%p] is corrupted.\n",
+ (void *) glyphSet);
+ #endif
+
+ return;
+ }
+
+ /*
+ * We loop across the list of glyphs id
+ * to establish if they have been added
+ * to glyphset on remote X server, so
+ * they can be freed.
+ */
+
+ tempGids = gids;
+
+ for (i = 0; i < nglyph; i++)
+ {
+ gid = (Glyph)*tempGids;
+
+ if ((gr = FindGlyphRef(&glyphSet -> hash, *tempGids, 0, 0)) &&
+ gr -> glyph != DeletedGlyph &&
+ gr -> corruptedGlyph == 0)
+ {
+ XRenderFreeGlyphs(nxagentDisplay, glyphSet -> remoteID, &gid, 1);
+ }
+
+ tempGids++;
+ }
+}
+
+void nxagentSetPictureTransform(PicturePtr pPicture, void * transform)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPictureTransform: Going to set transform [%p] to picture at [%p].\n",
+ (void *) transform, (void *) pPicture);
+ #endif
+
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureTransform(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ (XTransform *) transform);
+ #endif
+}
+
+void nxagentSetPictureFilter(PicturePtr pPicture, char *filter, int name_size,
+ void * params, int nparams)
+{
+ char *szFilter = Xmalloc(name_size + 1);
+
+ if (szFilter == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSetPictureFilter: error allocating memory for filter name.\n");
+ #endif
+
+ return;
+ }
+
+ strncpy(szFilter, filter, name_size);
+
+ szFilter[name_size] = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPictureFilter: Going to set filter [%s] to picture at [%p].\n",
+ szFilter, (void *) pPicture);
+ #endif
+/*
+FIXME: Is this useful or just a waste of bandwidth?
+
+ Apparently useless with QT.
+*/
+ #ifndef SKIP_LOUSY_RENDER_OPERATIONS
+
+ XRenderSetPictureFilter(nxagentDisplay,
+ nxagentPicturePriv(pPicture) -> picture,
+ szFilter,
+ (XFixed *) params,
+ nparams);
+ #endif
+
+ free(szFilter);
+}
+
+
+Bool nxagentPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ #ifdef RENDER
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentPictureInit: Screen [%p].\n", (void *) pScreen);
+ #endif
+
+ nxagentQueryFormats();
+
+ if (fbPictureInit(pScreen, formats, nformats) == 0)
+ {
+ return FALSE;
+ }
+
+ nxagentPicturePrivateIndex = AllocatePicturePrivateIndex();
+
+ AllocatePicturePrivate(pScreen, nxagentPicturePrivateIndex, sizeof(nxagentPrivPictureRec));
+
+ #endif
+
+ return TRUE;
+}
+
+#ifdef DEBUG
+
+static void nxagentPrintFormat(XRenderPictFormat *pFormat)
+{
+ if (pFormat == NULL)
+ {
+ fprintf(stderr, "nxagentPrintFormat: WARNING! null pointer passed to function.\n");
+
+ return;
+ }
+
+ fprintf(stderr, "nxagentPrintFormat: Dumping information for format at [%p]:\n\
+ type=%d\n\
+ depth=%d\n\
+ red=%d\n\
+ redMask=%d\n\
+ green=%d\n\
+ greenMask=%d\n\
+ blue=%d\n\
+ blueMask=%d\n\
+ alpha=%d\n\
+ alphaMask=%d\n",
+ (void *) pFormat,
+ pFormat -> type,
+ pFormat -> depth,
+ pFormat -> direct.red,
+ pFormat -> direct.redMask,
+ pFormat -> direct.green,
+ pFormat -> direct.greenMask,
+ pFormat -> direct.blue,
+ pFormat -> direct.blueMask,
+ pFormat -> direct.alpha,
+ pFormat -> direct.alphaMask);
+}
+
+#endif
+
+Bool nxagentFillGlyphSet(GlyphSetPtr pGly)
+{
+ GlyphPtr glyph;
+
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentFillGlyphSet: GlyphSet at [%p] Refcount [%ld] Glyphs [%ld] "
+ "Format [%p] FDepth [%d] RemoteID [%ld].\n", (void *) pGly, pGly -> refcnt,
+ pGly -> hash.hashSet -> size, (void *) pGly -> format, pGly -> fdepth, pGly -> remoteID);
+ #endif
+
+ /*
+ * The glyphs are synchronized when they
+ * are used in a composite text. During
+ * the reconnection we have only to mark
+ * corrupted the glyphs for each glyphset.
+ */
+
+ for (i = 0; i < pGly -> hash.hashSet -> size; i++)
+ {
+ glyph = pGly -> hash.table[i].glyph;
+
+ if (glyph && (glyph != DeletedGlyph))
+ {
+ pGly -> hash.table[i].corruptedGlyph = 1;
+ }
+ }
+
+ return TRUE;
+}
+
+void nxagentReconnectGlyphSet(void* p0, XID x1, void *p2)
+{
+ GlyphSetPtr pGly = (GlyphSetPtr) p0;
+
+ XRenderPictFormat *pForm = NULL;
+
+ int i;
+
+ if (nxagentReconnectTrap == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectGlyphSet: GlyphSet at [%p].\n", (void *) pGly);
+ #endif
+
+ if (pGly -> format)
+ {
+ pForm = nxagentMatchingFormats(pGly -> format);
+ }
+
+ pGly -> remoteID = XRenderCreateGlyphSet(nxagentDisplay, pForm);
+
+ /*
+ * If we have deferred the operation, we
+ * have to check the number of references
+ * to the glyphset to update the X server.
+ */
+
+ if ((i = pGly -> refcnt) > 1)
+ {
+ while (i-- > 1)
+ {
+ nxagentReferenceGlyphSet(pGly);
+ }
+ }
+
+ #ifdef DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ nxagentFillGlyphSet(pGly);
+ }
+ else
+ {
+ pGly -> remoteID = 0;
+ }
+}
+
+Bool nxagentReconnectAllGlyphSet(void *p)
+{
+ Bool success = TRUE;
+ int i;
+
+ nxagentQueryFormats();
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconnectAllGlyphSet\n");
+ #endif
+
+ for (i = 0; (i < MAXCLIENTS) && (success); i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], GlyphSetType, nxagentReconnectGlyphSet, &success);
+ }
+ }
+
+ return success;
+}
+
+void nxagentReconnectPicture(void * p0, XID x1, void *p2)
+{
+ PicturePtr pPicture = (PicturePtr) p0;
+ Bool *pBool = (Bool *) p2;
+ unsigned long mask = 0;
+
+ XRenderPictureAttributes attributes;
+ XRenderPictFormat *pForm;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Called with bool [%d] and picture at [%p].\n",
+ *pBool, (void *) pPicture);
+
+ fprintf(stderr, "nxagentReconnectPicture: Virtual picture is [%ld].\n",
+ nxagentPicture(pPicture));
+ #endif
+
+ /*
+ * Check if a previous operation has failed
+ * and that the involved objects are valid.
+ */
+
+ if (*pBool == 0 || pPicture == NULL ||
+ nxagentPicture(pPicture) != 0)
+ {
+ return;
+ }
+
+ if (pPicture -> repeat)
+ {
+ mask |= CPRepeat;
+
+ attributes.repeat = (Bool) pPicture -> repeat;
+ }
+
+ if (pPicture -> alphaMap)
+ {
+ if (!nxagentPicture(pPicture -> alphaMap))
+ {
+ nxagentReconnectPicture(pPicture -> alphaMap, 0, pBool);
+
+ if (!*pBool || !nxagentPicture(pPicture -> alphaMap))
+ {
+ return;
+ }
+ }
+
+ attributes.alpha_map = nxagentPicture(pPicture -> alphaMap);
+ attributes.alpha_x_origin = pPicture -> alphaOrigin.x;
+ attributes.alpha_y_origin = pPicture -> alphaOrigin.y;
+
+ mask |= (CPAlphaMap | CPAlphaXOrigin | CPAlphaYOrigin);
+ }
+
+ if (pPicture -> graphicsExposures)
+ {
+ attributes.graphics_exposures = pPicture -> graphicsExposures;
+
+ mask |= CPGraphicsExposure;
+ }
+
+ attributes.subwindow_mode = pPicture -> subWindowMode;
+
+ mask |= CPSubwindowMode;
+
+ attributes.poly_edge = pPicture -> polyEdge;
+
+ mask |= CPPolyEdge;
+
+ attributes.poly_mode = pPicture -> polyMode;
+
+ mask |= CPPolyMode;
+
+ attributes.dither = pPicture -> dither;
+
+ mask |= CPDither;
+
+ attributes.component_alpha = pPicture -> componentAlpha;
+
+ mask |= CPComponentAlpha;
+
+ pForm = NULL;
+
+ if (pPicture -> pFormat)
+ {
+ pForm = nxagentMatchingFormats(pPicture -> pFormat);
+
+ #ifdef DEBUG
+
+ nxagentPrintFormat(pForm);
+
+ #endif
+ }
+
+ if (!pForm && pPicture->pSourcePict)
+ {
+ /*possible we need to add support for other picture types, for example gradients...*/
+ switch(pPicture->pSourcePict->type)
+ {
+ case SourcePictTypeSolidFill:
+ nxagentPicturePriv(pPicture) -> picture = XRenderCreateSolidFill(nxagentDisplay,
+ (const XRenderColor*) &pPicture->pSourcePict->solidFill.fullColor);
+ break;
+ }
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Creating picture at [%p] with drawable [%ld] at [%p].\n",
+ (void *) pPicture, nxagentDrawable(pPicture -> pDrawable), (void *) pPicture -> pDrawable);
+
+ fprintf(stderr, "nxagentReconnectPicture: Format is at [%p] mask is [%ld] attributes are at [%p].\n",
+ (void *) pForm, mask, (void *) &attributes);
+ #endif
+
+ nxagentPicture(pPicture) = XRenderCreatePicture(nxagentDisplay,
+ nxagentDrawable(pPicture -> pDrawable),
+ pForm,
+ mask,
+ &attributes);
+
+ #ifdef TEST
+
+ XSync(nxagentDisplay, 0);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectPicture: Reconnected picture at [%p] with value [%ld].\n",
+ (void *) pPicture, nxagentPicture(pPicture));
+ #endif
+
+ if (nxagentAlphaEnabled == 1 && pPicture -> pDrawable -> depth == 32 &&
+ pPicture -> pFormat -> direct.alpha != 0)
+ {
+ if (pPicture -> pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv((PixmapPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ else if (pPicture -> pDrawable -> type == DRAWABLE_WINDOW)
+ {
+ nxagentWindowPriv((WindowPtr) pPicture -> pDrawable) -> pPicture = pPicture;
+ }
+ }
+}
+
+Bool nxagentReconnectAllPicture(void *p)
+{
+ int i;
+ Bool r;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectAllPicture: Going to recreate all pictures.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], PictureType, nxagentReconnectPicture, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentReconnectAllPicture: WARNING! Failed to recreate "
+ "picture for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+
+void nxagentDisconnectPicture(void * p0, XID x1, void* p2)
+{
+ PicturePtr pPicture = (PicturePtr) p0;
+ Bool *pBool = (Bool *) p2;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDisconnectPicture: Called with bool [%d] and picture at [%p].\n",
+ *pBool, (void *) pPicture);
+
+ fprintf(stderr, "nxagentDisconnectPicture: Virtual picture is [%ld].\n",
+ nxagentPicture(pPicture));
+ #endif
+
+ if (!*pBool || !pPicture)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisconnectPicture: %p - XID %lx\n",
+ (void *) pPicture, nxagentPicture(pPicture));
+ #endif
+
+ nxagentPicture(pPicture) = None;
+}
+
+Bool nxagentDisconnectAllPicture()
+{
+ int i;
+ Bool r;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDisconnectAllPicture.\n");
+ #endif
+
+ for (i = 0, r = 1; i < MAXCLIENTS; i++)
+ {
+ if (clients[i])
+ {
+ FindClientResourcesByType(clients[i], PictureType, nxagentDisconnectPicture, &r);
+
+ #ifdef WARNING
+
+ if (r == False)
+ {
+ fprintf(stderr, "nxagentDisconnectAllPicture: WARNING! Failed to disconnect "
+ "picture for client [%d].\n", i);
+ }
+
+ #endif
+ }
+ }
+
+ return True;
+}
+
+void nxagentRenderCreateSolidFill(PicturePtr pPicture, xRenderColor *color)
+{
+ Picture id;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateSolidFill: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (color == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateSolidFill: WARNING! color pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ id = XRenderCreateSolidFill(nxagentDisplay, (XRenderColor *) color);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateSolidFill: Created solid fill xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateLinearGradient(PicturePtr pPicture, xPointFixed *p1,
+ xPointFixed *p2, int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XLinearGradient linearGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (p1 == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p1 pointer is NULL.\n");
+ }
+
+ if (p2 == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! p2 pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ linearGradient.p1.x = (XFixed) p1 -> x;
+ linearGradient.p1.y = (XFixed) p1 -> y;
+ linearGradient.p2.x = (XFixed) p2 -> x;
+ linearGradient.p2.y = (XFixed) p2 -> y;
+
+ id = XRenderCreateLinearGradient(nxagentDisplay, &linearGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateLinearGradient: Created linear gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateRadialGradient(PicturePtr pPicture, xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XRadialGradient radialGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (inner == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! inner pointer is NULL.\n");
+ }
+
+ if (outer == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! outer pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ radialGradient.inner.x = (XFixed) inner -> x;
+ radialGradient.inner.y = (XFixed) inner -> y;
+ radialGradient.inner.radius = (XFixed) innerRadius;
+ radialGradient.outer.x = (XFixed) outer -> x;
+ radialGradient.outer.y = (XFixed) outer -> y;
+ radialGradient.outer.radius = (XFixed) outerRadius;
+
+ id = XRenderCreateRadialGradient(nxagentDisplay, &radialGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateRadialGradient: Created radial gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
+void nxagentRenderCreateConicalGradient(PicturePtr pPicture,
+ xPointFixed *center,
+ xFixed angle, int nStops,
+ xFixed *stops,
+ xRenderColor *colors)
+{
+ Picture id;
+
+ XConicalGradient conicalGradient;
+
+ if (nxagentRenderEnable == False)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: Got called.\n");
+
+ if (pPicture == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! pPicture pointer is NULL.\n");
+ }
+
+ if (center == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! center pointer is NULL.\n");
+ }
+
+ if (stops == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! stops pointer is NULL.\n");
+ }
+
+ if (colors == NULL)
+ {
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: WARNING! colors pointer is NULL.\n");
+ }
+
+ #endif /* #ifdef DEBUG */
+
+ memset(&(nxagentPicturePriv(pPicture) -> lastServerValues), 0,
+ sizeof(XRenderPictureAttributes_));
+
+ conicalGradient.center.x = (XFixed) center -> x;
+ conicalGradient.center.y = (XFixed) center -> y;
+ conicalGradient.angle = (XFixed) angle;
+
+ id = XRenderCreateConicalGradient(nxagentDisplay, &conicalGradient,
+ (XFixed *) stops,
+ (XRenderColor *) colors, nStops);
+
+ #ifdef DEBUG
+ XSync(nxagentDisplay, 0);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRenderCreateConicalGradient: Created conical gradient xid [%lu].\n", id);
+ #endif
+
+ nxagentPicturePriv(pPicture) -> picture = id;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Render.h b/nx-X11/programs/Xserver/hw/nxagent/Render.h
new file mode 100644
index 000000000..1c56ec16b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Render.h
@@ -0,0 +1,119 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Render_H__
+#define __Render_H__
+
+#include "screenint.h"
+#include "cursor.h"
+#include "picture.h"
+#include "renderproto.h"
+
+#include "glyphstr.h"
+
+#include "Agent.h"
+
+extern int nxagentRenderEnable;
+extern int nxagentRenderVersionMajor;
+extern int nxagentRenderVersionMinor;
+
+extern int nxagentPicturePrivateIndex;
+
+extern BoxPtr nxagentGlyphsExtents;
+extern BoxPtr nxagentTrapezoidExtents;
+
+/*
+ * Structure imported from Xrender.h. We don't
+ * include Xrender.h at this point because of
+ * clashes of definition.
+ */
+
+/*
+ * Xlib Pixmap and Atom types are 8 bytes long
+ * on 64-bit archs, whilst they are 4 bytes long
+ * on 32-bit ones. At this point, Pixmap and Atom
+ * are not Xlib types but Xserver ones: here they
+ * are always 4 bytes long. So that we use XlibID
+ * symbols defined below to fill the structure with
+ * fields having the right size.
+ */
+
+typedef struct {
+ int repeat;
+ Picture alpha_map;
+ int alpha_x_origin;
+ int alpha_y_origin;
+ int clip_x_origin;
+ int clip_y_origin;
+ XlibPixmap clip_mask;
+ Bool graphics_exposures;
+ int subwindow_mode;
+ int poly_edge;
+ int poly_mode;
+ XlibAtom dither;
+ Bool component_alpha;
+} XRenderPictureAttributes_;
+
+typedef struct
+{
+ Picture picture;
+
+ XRenderPictureAttributes_ lastServerValues;
+
+} nxagentPrivPictureRec;
+
+typedef nxagentPrivPictureRec *nxagentPrivPicturePtr;
+
+#define nxagentPicturePriv(pPicture) \
+ ((nxagentPrivPicturePtr) ((pPicture) -> devPrivates[nxagentPicturePrivateIndex].ptr))
+
+#define nxagentPicture(pPicture) (nxagentPicturePriv(pPicture) -> picture)
+
+#define nxagentSetPictureRemoteValue(pPicture, pvalue, value) \
+do \
+{ \
+ nxagentPicturePriv(pPicture) -> lastServerValues.pvalue = value; \
+} \
+while (0)
+
+#define nxagentCheckPictureRemoteValue(pPicture, pvalue, value) \
+ (nxagentPicturePriv(pPicture) -> lastServerValues.pvalue == value)
+
+void nxagentRenderExtensionInit(void);
+Bool nxagentPictureInit(ScreenPtr, PictFormatPtr, int);
+
+int nxagentRenderRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+
+void nxagentAddGlyphs(GlyphSetPtr glyphSet, Glyph *gids, xGlyphInfo *gi,
+ int nglyphs, CARD8 *images, int sizeImages);
+
+void nxagentReconnectPicture(void * p0, XID x1, void *p2);
+void nxagentDisconnectPicture(void * p0, XID x1, void* p2);
+
+void nxagentReconnectGlyphSet(void* p0, XID x1, void *p2);
+
+void nxagentDestroyPicture(PicturePtr pPicture);
+
+#endif /* __Render_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Rootless.c b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c
new file mode 100644
index 000000000..f42f9d99d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.c
@@ -0,0 +1,1291 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "X.h"
+
+#include "../../include/window.h"
+#include "windowstr.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "propertyst.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Drawable.h"
+#include "Windows.h"
+#include "Pixmaps.h"
+#include "Atoms.h"
+#include "Trap.h"
+#include "Utils.h"
+
+#include "compext/Compext.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Assigned at the time the root window is
+ * initialized.
+ */
+
+typedef struct
+{
+ CARD32 flags;
+ CARD32 input;
+ CARD32 initial_state;
+ CARD32 icon_pixmap;
+ CARD32 icon_window;
+ INT32 icon_x;
+ INT32 icon_y;
+ CARD32 icon_mask;
+ CARD32 window_group;
+}
+nxagentWMHints;
+
+/*
+ * This structure is compatible with 32
+ * and 64 bit library interface. It has
+ * been copied from Xatomtype.h and it's
+ * a parameter of XChangeProperty().
+ */
+
+typedef struct
+{
+ unsigned long flags;
+ long input;
+ long initialState;
+ unsigned long iconPixmap;
+ unsigned long iconWindow;
+ long iconX;
+ long iconY;
+ unsigned long iconMask;
+ unsigned long windowGroup;
+}
+nxagentPropWMHints;
+
+WindowPtr nxagentRootlessWindow = NULL;
+
+#define TOP_LEVEL_TABLE_UNIT 100
+
+typedef struct {
+ Window xid;
+ WindowPtr pWin;
+} TopLevelParentRec;
+
+typedef struct {
+ TopLevelParentRec *elt;
+ int next;
+ int size;
+} TopLevelParentMap;
+
+static TopLevelParentMap topLevelParentMap = { NULL, 0, 0 };
+
+static void nxagentRemovePropertyFromList(void);
+
+/*
+ * This is currently unused.
+ */
+
+#ifdef TEST
+
+static void nxagentPrintRootlessTopLevelWindowMap(void);
+
+void nxagentPrintRootlessTopLevelWindowMap()
+{
+ int i;
+
+ fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: Map size is [%d] num of entry [%d].\n",
+ topLevelParentMap.size, topLevelParentMap.next);
+
+ for (i = 0; i < topLevelParentMap.next; i++)
+ {
+ fprintf(stderr, "nxagentPrintRootlessTopLevelWindowMap: [%d] pWin at [%p] XID at [%ld].\n",
+ i, (void *) topLevelParentMap.elt[i].pWin, (long int) topLevelParentMap.elt[i].xid);
+ }
+}
+
+#endif
+
+void nxagentRootlessAddTopLevelWindow(WindowPtr pWin, Window w)
+{
+ int i;
+
+ for (i = 0; i < topLevelParentMap.next; i++)
+ {
+ if (topLevelParentMap.elt[i].pWin == pWin)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentRootlessAddTopLevelWindow: WARNING! "
+ "Trying to add duplicated entry window at [%p] xid [%ld].\n",
+ (void *) pWin, w);
+ #endif
+
+ topLevelParentMap.elt[i].xid = w;
+
+ return;
+ }
+ }
+
+ if (topLevelParentMap.next == topLevelParentMap.size)
+ {
+ TopLevelParentRec *ptr = topLevelParentMap.elt;
+ size_t size = (topLevelParentMap.size += TOP_LEVEL_TABLE_UNIT);
+
+ ptr = realloc(ptr, size * sizeof(TopLevelParentRec));
+
+ if (ptr == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRootlessAddTopLevelWindow: Warning failed to allocate memory.\n");
+ #endif
+
+ return;
+ }
+
+ topLevelParentMap.elt = ptr;
+ topLevelParentMap.size = size;
+ }
+
+ topLevelParentMap.elt[topLevelParentMap.next].xid = w;
+ topLevelParentMap.elt[topLevelParentMap.next].pWin = pWin;
+ topLevelParentMap.next++;
+}
+
+WindowPtr nxagentRootlessTopLevelWindow(Window w)
+{
+ int i;
+
+ for (i = 0; i < topLevelParentMap.next; i++)
+ {
+ if (w == topLevelParentMap.elt[i].xid)
+ {
+ return topLevelParentMap.elt[i].pWin;
+ }
+ }
+
+ return NULL;
+}
+
+void nxagentRootlessDelTopLevelWindow(WindowPtr pWin)
+{
+ int i;
+
+ for (i = 0; i < topLevelParentMap.next; i++)
+ {
+ if (pWin == topLevelParentMap.elt[i].pWin)
+ {
+ topLevelParentMap.elt[i] = topLevelParentMap.elt[topLevelParentMap.next - 1];
+ topLevelParentMap.next--;
+
+ return;
+ }
+ }
+}
+
+Window nxagentRootlessWMTopLevelWindow(WindowPtr pWin);
+
+void nxagentConfigureRootlessWindow(WindowPtr pWin, int x, int y, int w, int h, int bw,
+ WindowPtr pSib, int stack_mode, Mask mask)
+{
+ XWindowChanges changes;
+ Window sibw = 0;
+
+ changes.x = x;
+ changes.y = y;
+ changes.width = w;
+ changes.height = h;
+ changes.border_width = bw;
+ changes.stack_mode = stack_mode;
+
+ if (pSib)
+ {
+ sibw = nxagentWindow(pSib);
+ }
+
+ if (sibw)
+ {
+ changes.sibling = sibw;
+ }
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes);
+}
+
+void nxagentCirculateRootlessWindows(int direction)
+{
+ XCirculateSubwindows(nxagentDisplay, DefaultRootWindow(nxagentDisplay), direction);
+}
+
+#ifdef DEBUG
+
+Bool nxagentRootlessTreesMatch()
+{
+ Window root_return;
+ Window parent_return;
+ Window *children_return;
+ unsigned int nChildrenReturn;
+ WindowPtr pW;
+ WindowPtr pTestWin = screenInfo.screens[0]->root -> firstChild;
+ Bool treesMatch = True;
+ Status result;
+
+ result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ &root_return, &parent_return, &children_return, &nChildrenReturn);
+
+ if (!result)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentRootlessTreesMatch: WARNING! Failed QueryTree request.\n");
+ #endif
+
+ return False;
+ }
+
+ while (nChildrenReturn > 0)
+ {
+ pW = nxagentWindowPtr(children_return[--nChildrenReturn]);
+
+ if (!pW)
+ {
+ pW = nxagentRootlessTopLevelWindow(children_return[nChildrenReturn]);
+ }
+
+ if (pW && pW != screenInfo.screens[0]->root)
+ {
+ if (treesMatch && pTestWin && pTestWin == pW)
+ {
+ pTestWin = pTestWin -> nextSib;
+ }
+ else
+ {
+ treesMatch = False;
+ }
+ }
+ }
+
+ if (children_return)
+ {
+ XFree(children_return);
+ }
+
+ return treesMatch;
+}
+
+#endif
+
+#ifndef _XSERVER64
+void nxagentRootlessRestack(Window children[], unsigned int nchildren)
+#else
+void nxagentRootlessRestack(unsigned long children[], unsigned int nchildren)
+#endif
+{
+ WindowPtr *toplevel;
+ unsigned int ntoplevel;
+ int i;
+ WindowPtr pWin;
+ ClientPtr pClient;
+ XID values[2];
+ Mask mask;
+
+ toplevel = malloc(sizeof(WindowPtr) * nchildren);
+
+ if (!toplevel)
+ {
+ /* FIXME: Is this too much and we and simply return here? */
+ FatalError("nxagentRootlessRestack: malloc() failed.");
+ }
+
+ ntoplevel = 0;
+
+ for(i = 0; i < nchildren; i++)
+ {
+ pWin = nxagentWindowPtr(children[i]);
+
+ if (!pWin)
+ {
+ pWin = nxagentRootlessTopLevelWindow(children[i]);
+ }
+
+ if (pWin && pWin != screenInfo.screens[0]->root)
+ {
+ toplevel[ntoplevel++] = pWin;
+ }
+ }
+
+ if (!ntoplevel)
+ {
+ free(toplevel);
+ return;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRootlessRestack: External top level windows before restack:");
+
+ for (i = 0; i < ntoplevel; i++)
+ {
+ fprintf(stderr, "nxagentRootlessRestack: [%p]\n", toplevel[i]);
+ }
+
+ fprintf(stderr, "nxagentRootlessRestack: Internal top level windows before restack:");
+
+ for (pWin = screenInfo.screens[0]->root -> firstChild; pWin != NULL; pWin = pWin -> nextSib)
+ {
+ fprintf(stderr, "nxagentRootlessRestack: [%p]\n", pWin);
+ }
+
+ #endif
+
+ pWin = screenInfo.screens[0]->root -> firstChild;
+
+ values[1] = (XID) Above;
+
+ while(ntoplevel-- > 0 && pWin != NULL)
+ {
+ if (toplevel[ntoplevel] != pWin)
+ {
+ mask = CWSibling | CWStackMode;
+ values[0] = pWin -> drawable.id;
+ pClient = wClient(toplevel[ntoplevel]);
+ nxagentScreenTrap = 1;
+ ConfigureWindow(toplevel[ntoplevel], mask, (XID *) values, pClient);
+ nxagentScreenTrap = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRootlessRestack: Restacked window [%p].\n", (void*) toplevel[ntoplevel]);
+ #endif
+ }
+
+ pWin = toplevel[ntoplevel] -> nextSib;
+ }
+
+ #ifdef DEBUG
+
+ fprintf(stderr, "nxagentRootlessRestack: External top level windows after restack:");
+
+ ntoplevel = i;
+
+ for (i = 0; i < ntoplevel; i++)
+ {
+ fprintf(stderr, "nxagentRootlessRestack: [%p]\n", toplevel[i]);
+ }
+
+ fprintf(stderr, "nxagentRootlessRestack: Internal top level windows after restack:");
+
+ for (pWin = screenInfo.screens[0]->root -> firstChild; pWin != NULL; pWin = pWin -> nextSib)
+ {
+ fprintf(stderr, "nxagentRootlessRestack: [%p]\n", pWin);
+ }
+
+ #endif
+
+ free(toplevel);
+
+ return;
+}
+
+/*
+ * Determine if window is a top-level window.
+ */
+
+Window nxagentRootlessWindowParent(WindowPtr pWin)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentRootlessWindowParent: Called for window at [%p][%ld] with parent [%p][%ld].\n",
+ (void *) pWin, nxagentWindowPriv(pWin)->window, (void *) pWin->parent,
+ (pWin->parent ? nxagentWindowPriv(pWin->parent)->window : 0));
+ #endif
+
+ if (pWin -> parent == NULL)
+ {
+ return DefaultRootWindow(nxagentDisplay);
+ }
+ else if (pWin -> parent == nxagentRootlessWindow)
+ {
+ return DefaultRootWindow(nxagentDisplay);
+ }
+ else
+ {
+ return nxagentWindow(pWin -> parent);
+ }
+}
+
+int nxagentExportAllProperty(pWin)
+ WindowPtr pWin;
+{
+ PropertyPtr pProp;
+ int total = 0;
+
+ for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
+ {
+ total += nxagentExportProperty(pWin,
+ pProp->propertyName,
+ pProp->type,
+ pProp->format,
+ PropModeReplace,
+ pProp->size,
+ pProp->data);
+ }
+
+ return total;
+}
+
+int nxagentExportProperty(pWin, property, type, format, mode, nUnits, value)
+ WindowPtr pWin;
+ Atom property, type;
+ int format, mode;
+ unsigned long nUnits;
+ void *value;
+{
+ const char *propertyS, *typeS;
+ Atom propertyX, typeX;
+ char *output = NULL;
+ nxagentWMHints wmHints;
+ nxagentPropWMHints propHints;
+ Bool export = False;
+ Bool freeMem = False;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return 0;
+ }
+
+ propertyS = NameForAtom(property);
+ typeS = NameForAtom(type);
+
+ if (strncmp(propertyS, "WM_", 3) != 0 &&
+ strncmp(propertyS, "_NET_", 5) != 0 &&
+ strcmp(propertyS, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR") != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty "
+ "on %swindow %lx property %s type %s nUnits %ld format %d\n",
+ nxagentWindowTopLevel(pWin) ? "toplevel " : "", nxagentWindow(pWin),
+ validateString(propertyS), validateString(typeS), nUnits, format);
+ #endif
+ }
+ else if (strcmp(typeS, "STRING") == 0 ||
+ #ifndef _XSERVER64
+ strcmp(typeS, "CARDINAL") == 0 ||
+ strcmp(typeS, "WM_SIZE_HINTS") == 0 ||
+ #endif
+ strcmp(typeS, "UTF8_STRING") == 0)
+ {
+ output = value;
+ export = True;
+ }
+ #ifdef _XSERVER64
+ else if (strcmp(typeS, "CARDINAL") == 0 || strcmp(typeS, "WM_SIZE_HINTS") == 0)
+ {
+ /* FIXME: is it okay here to ignore malloc fails? */
+ unsigned long *buffer = malloc(nUnits * sizeof(*buffer));
+ int *input = value;
+ int i;
+
+ if (buffer)
+ {
+ freeMem = True;
+ export = True;
+ output = (char*) buffer;
+
+ for (i = 0; i < nUnits; i++)
+ {
+ buffer[i] = input[i];
+ }
+ }
+ }
+ #endif
+ else if (strcmp(typeS, "WM_HINTS") == 0)
+ {
+ ClientPtr pClient = wClient(pWin);
+ wmHints = *(nxagentWMHints*)value;
+
+ wmHints.flags |= InputHint;
+ wmHints.input = True;
+
+ /*
+ * Initialize the structure used in XChangeProperty().
+ */
+
+ propHints.flags = wmHints.flags;
+ propHints.input = (wmHints.input == True ? 1 : 0);
+ propHints.initialState = wmHints.initial_state;
+ propHints.iconPixmap = wmHints.icon_pixmap;
+ propHints.iconWindow = wmHints.icon_window;
+ propHints.iconX = wmHints.icon_x;
+ propHints.iconY = wmHints.icon_y;
+ propHints.iconMask = wmHints.icon_mask;
+ propHints.windowGroup = wmHints.window_group;
+
+ output = (char*) &propHints;
+ export = True;
+
+ if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None))
+ {
+ PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_pixmap,
+ RT_PIXMAP, DixDestroyAccess);
+
+ if (icon)
+ {
+ if (nxagentDrawableStatus((DrawablePtr) icon) == NotSynchronized)
+ {
+ nxagentSynchronizeRegion((DrawablePtr) icon, NullRegion, NEVER_BREAK, NULL);
+ }
+
+ propHints.iconPixmap = nxagentPixmap(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconPixmapHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon pixmap %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) wmHints.icon_pixmap, propertyS, typeS,
+ (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window != None))
+ {
+ WindowPtr icon = (WindowPtr)SecurityLookupWindow(wmHints.icon_window, pClient,
+ DixDestroyAccess);
+
+ if (icon)
+ {
+ propHints.iconWindow = nxagentWindow(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconWindowHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon window %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) wmHints.icon_window, propertyS, typeS,
+ (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask != None))
+ {
+ PixmapPtr icon = (PixmapPtr)SecurityLookupIDByType(pClient, wmHints.icon_mask,
+ RT_PIXMAP, DixDestroyAccess);
+
+ if (icon)
+ {
+ propHints.iconMask = nxagentPixmap(icon);
+ }
+ else
+ {
+ propHints.flags &= ~IconMaskHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up icon mask %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) wmHints.icon_mask, propertyS, typeS,
+ (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None))
+ {
+ WindowPtr window = (WindowPtr)SecurityLookupWindow(wmHints.window_group, pClient,
+ DixDestroyAccess);
+
+ if (window)
+ {
+ propHints.windowGroup = nxagentWindow(window);
+ }
+ else
+ {
+ propHints.flags &= ~WindowGroupHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window group %x from hint "
+ "exporting property %s type %s on window %p.\n",
+ (unsigned int) wmHints.window_group, propertyS, typeS,
+ (void *) pWin);
+ #endif
+ }
+ }
+ }
+ else if (strcmp(typeS, "ATOM") == 0)
+ {
+ XlibAtom *atoms = malloc(nUnits * sizeof(*atoms));
+ Atom *input = value;
+ const char *atomName = NULL;
+ int i;
+ int j = 0;
+
+ if (!atoms)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! malloc() failed for '%s'- bailing out.\n", typeS);
+ #endif
+ return False;
+ }
+
+ freeMem = True;
+ export = True;
+ output = (char *) atoms;
+
+ for (i = 0; i < nUnits; i++)
+ {
+ /*
+ * Exporting the _NET_WM_PING property could
+ * result in rootless windows being grayed out
+ * when the compiz window manager is running.
+ *
+ * Better solution would probably be to handle
+ * the communication with the window manager
+ * instead of just getting rid of the property.
+ */
+
+ if ((atomName = NameForAtom(input[i])) != NULL &&
+ strcmp(atomName, "_NET_WM_PING") != 0)
+ {
+ atoms[j] = nxagentLocalToRemoteAtom(input[i]);
+
+ if (atoms[j] == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom %ld [%s].\n",
+ (long int) input[i], validateString(atomName));
+ #endif
+ }
+
+ j++;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentExportProperty: WARNING! "
+ "Not exporting the _NET_WM_PING property.\n");
+ }
+ #endif
+ }
+
+ nUnits = j;
+ }
+ else if (strcmp(typeS, "WINDOW") == 0)
+ {
+ Window *input = value;
+ XlibWindow *wind = malloc(nUnits * sizeof(*wind));
+ ClientPtr pClient = wClient(pWin);
+ WindowPtr pWindow;
+ int i;
+
+ if (!wind)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! malloc() failed for '%s' - bailing out.\n", typeS);
+ #endif
+ return False;
+ }
+
+ freeMem = True;
+ export = True;
+ output = (char*) wind;
+
+ for (i = 0; i < nUnits; i++)
+ {
+ pWindow = (WindowPtr)SecurityLookupWindow(input[i], pClient,
+ DixDestroyAccess);
+ if ((input[i] != None) && pWindow)
+ {
+ wind[i] = nxagentWindow(pWindow);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to look up window %ld "
+ "exporting property %s type %s on window %p.\n",
+ (long int) input[i], propertyS, typeS, (void *) pWin);
+ #endif
+
+ /*
+ * It seems that clients specifie
+ * strange windows, perhaps are
+ * not real windows so we can try
+ * to let them pass anyway.
+ *
+ * wind[i] = None;
+ *
+ */
+ }
+ }
+ }
+
+ if (export)
+ {
+ propertyX = nxagentLocalToRemoteAtom(property);
+ typeX = nxagentLocalToRemoteAtom(type);
+
+ if (propertyX == None || typeX == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! Failed to convert local atom.\n");
+ #endif
+
+ export = 0;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExportProperty: Property [%lu] format [%i] "
+ "units [%lu].\n", propertyX, format, nUnits);
+ #endif
+
+ if ((format >> 3) * nUnits + sizeof(xChangePropertyReq) <
+ (MAX_REQUEST_SIZE << 2))
+ {
+ XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX, typeX,
+ format, mode, (void*)output, nUnits);
+ }
+ else if (mode == PropModeReplace)
+ {
+ int n;
+ char *data;
+
+ XDeleteProperty(nxagentDisplay, nxagentWindow(pWin), propertyX);
+
+ data = (char *) output;
+
+ while (nUnits > 0)
+ {
+ if ((format >> 3) * nUnits + sizeof(xChangePropertyReq) <
+ (MAX_REQUEST_SIZE << 2))
+ {
+ n = nUnits;
+ }
+ else
+ {
+ n = ((MAX_REQUEST_SIZE << 2) - sizeof(xChangePropertyReq)) /
+ (format >> 3);
+ }
+
+ XChangeProperty(nxagentDisplay, nxagentWindow(pWin), propertyX,
+ typeX, format, PropModeAppend, (void*) data, n);
+
+ nUnits -= n;
+
+ data = (char *) data + n * (format >> 3);
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentExportProperty: WARNING! "
+ "Property [%lu] too long.\n", (long unsigned int)propertyX);
+ #endif
+
+ goto nxagentExportPropertyError;
+ }
+
+ nxagentAddPropertyToList(propertyX, pWin);
+ }
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentExportProperty: WARNING! Ignored ChangeProperty "
+ "on %swindow %x property %s type %s nUnits %ld format %d\n",
+ nxagentWindowTopLevel(pWin) ? "toplevel " : "",
+ nxagentWindow(pWin), validateString(propertyS), validateString(typeS),
+ nUnits, format);
+ #endif
+ }
+
+ nxagentExportPropertyError:
+
+ if (freeMem)
+ {
+ free(output);
+ }
+
+ return export;
+}
+
+void nxagentImportProperty(Window window,
+ Atom property,
+ Atom type,
+ int format,
+ unsigned long nitems,
+ unsigned long bytes_after,
+ unsigned char *buffer)
+{
+ Atom propertyL;
+ Atom typeL;
+
+ WindowPtr pWin;
+ Bool import = False;
+ Bool freeMem = False;
+ nxagentWMHints wmHints;
+
+ typedef struct {
+ CARD32 state;
+ Window icon;
+ } WMState;
+ WMState wmState;
+
+ char *output = NULL;
+ const char *typeS;
+
+ pWin = nxagentWindowPtr(window);
+
+ if (pWin == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: Failed to look up remote window %lx property [%ld] exiting.\n",
+ window, property);
+ #endif
+
+ return;
+ }
+
+ propertyL = nxagentRemoteToLocalAtom(property);
+
+ if (!ValidAtom(propertyL))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: Failed to convert remote property atom.\n");
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: Window %lx property [%ld]: %s\n",
+ window, property, validateString(NameForAtom(propertyL)));
+ #endif
+
+ /*
+ * We settle a property size limit of
+ * 256K beyond which we simply ignore them.
+ */
+
+ typeL = nxagentRemoteToLocalAtom(type);
+ typeS = NameForAtom(typeL);
+
+ if (buffer == NULL && (nitems > 0))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: Failed to retrieve remote property [%ld] %s on Window %ld\n",
+ (long int) property, validateString(NameForAtom(propertyL)), (long int) window);
+ #endif
+ }
+ else if (bytes_after != 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: Remote property bigger than maximum limits.\n");
+ #endif
+ }
+ else if (!ValidAtom(typeL))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: Failed to convert remote atoms [%ld].\n",
+ (long int) type);
+ #endif
+ }
+ else if (nitems == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: Importing void property.\n");
+ #endif
+
+ import = True;
+ }
+ else if (strcmp(typeS, "STRING") == 0 ||
+ strcmp(typeS, "UTF8_STRING") == 0 ||
+ strcmp(typeS, "CARDINAL") == 0 ||
+ strcmp(typeS, "WM_SIZE_HINTS") == 0)
+ {
+ output = (char*)buffer;
+ import = True;
+ }
+ else if (strcmp(typeS, "WM_STATE") == 0)
+ {
+ /*
+ * Contents of property of type WM_STATE
+ * are {CARD32 state, WINDOW icon}. Only
+ * the icon field has to be modified before
+ * importing the property.
+ */
+
+ WindowPtr pIcon;
+
+ wmState = *(WMState*)buffer;
+ pIcon = nxagentWindowPtr(wmState.icon);
+
+ if (pIcon || wmState.icon == None)
+ {
+ import = True;
+ output = (char*) &wmState;
+ wmState.icon = pIcon ? nxagentWindow(pIcon) : None;
+ }
+ else if (wmState.icon)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote window %ld"
+ " importing property %ld of type WM_STATE", (long int) wmState.icon,
+ (long int) property);
+ #endif
+ }
+ }
+ else if (strcmp(typeS, "WM_HINTS") == 0)
+ {
+ wmHints = *(nxagentWMHints*)buffer;
+ output = (char*) &wmHints;
+ import = True;
+
+ if ((wmHints.flags & IconPixmapHint) && (wmHints.icon_pixmap != None))
+ {
+ PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_pixmap);
+
+ if (icon)
+ {
+ wmHints.icon_pixmap = icon -> drawable.id;
+ }
+ else
+ {
+ wmHints.flags &= ~IconPixmapHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon "
+ "pixmap %d from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) wmHints.icon_pixmap, (long int) property,
+ typeS, (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & IconWindowHint) && (wmHints.icon_window != None))
+ {
+ WindowPtr icon = nxagentWindowPtr(wmHints.icon_window);
+
+ if (icon)
+ {
+ wmHints.icon_window = icon -> drawable.id;
+ }
+ else
+ {
+ wmHints.flags &= ~IconWindowHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagenImportProperty: WARNING! Failed to look up remote icon "
+ "window %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) wmHints.icon_window,
+ (long int) property, typeS, (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & IconMaskHint) && (wmHints.icon_mask != None))
+ {
+ PixmapPtr icon = nxagentPixmapPtr(wmHints.icon_mask);
+
+ if (icon)
+ {
+ wmHints.icon_mask = icon -> drawable.id;
+ }
+ else
+ {
+ wmHints.flags &= ~IconMaskHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote icon "
+ "mask %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) wmHints.icon_mask, (long int) property, typeS, (void *) pWin);
+ #endif
+ }
+ }
+
+ if ((wmHints.flags & WindowGroupHint) && (wmHints.window_group != None))
+ {
+ WindowPtr group = nxagentWindowPtr(wmHints.window_group);
+
+ if (group)
+ {
+ wmHints.window_group = group -> drawable.id;
+ }
+ else
+ {
+ wmHints.flags &= ~WindowGroupHint;
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window "
+ "group %x from hint importing property [%ld] type %s on window %p.\n",
+ (unsigned int) wmHints.window_group,
+ (long int) property, typeS, (void *) pWin);
+ #endif
+ }
+ }
+ }
+ else if (strcmp(typeS, "ATOM") == 0)
+ {
+ Atom *atoms = malloc(nitems * sizeof(Atom));
+ Atom *input = (Atom*) buffer;
+ int i;
+
+ if (atoms == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! malloc() failed for '%s' - bailing out.\n", typeS);
+ #endif
+
+ return;
+ }
+
+ freeMem = True;
+ import = True;
+ output = (char *) atoms;
+
+ for (i = 0; i < nitems; i++)
+ {
+ atoms[i] = nxagentRemoteToLocalAtom(input[i]);
+
+ if (atoms[i] == None)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to convert remote atom %ld.\n",
+ (long int) input[i]);
+ #endif
+ }
+ }
+ }
+ else if (strcmp(typeS, "WINDOW") == 0)
+ {
+ Window *input = (Window*) buffer;
+ Window *wind = malloc(nitems * sizeof(Window));
+ WindowPtr pWindow;
+ int i;
+
+ if (!wind)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! malloc() failed for '%s' - bailing out.\n", typeS);
+ #endif
+
+ return;
+ }
+ freeMem = True;
+ import = True;
+ output = (char*) wind;
+
+ for (i = 0; i < nitems; i++)
+ {
+ pWindow = nxagentWindowPtr(input[i]);
+
+ if (pWindow)
+ {
+ wind[i] = pWindow -> drawable.id;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentImportProperty: WARNING! Failed to look up remote window %lx "
+ "importing property [%ld] type %s on window %p.\n",
+ (long int) input[i], (long int) property, typeS, (void*)pWin);
+ #endif
+
+ wind[i] = None;
+ }
+ }
+ }
+
+ if (import)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: ChangeProperty "
+ "on window %lx property [%ld] type %s nitems %ld format %d\n",
+ window, property, typeS, nitems, format);
+ #endif
+
+ ChangeWindowProperty(pWin, propertyL, typeL, format,
+ PropModeReplace, nitems, output, 1);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentImportProperty: WARNING! Ignored ChangeProperty "
+ "on window %lx property [%ld] type %s ntems %ld format %d\n",
+ window, property, validateString(typeS), nitems, format);
+ #endif
+ }
+
+ if (freeMem)
+ {
+ free(output);
+ }
+
+ return;
+}
+
+/*
+ * We want to import all properties changed by external clients to
+ * reflect properties of our internal windows but we must ignore
+ * all the property notify events generated by our own requests.
+ * For this purpose we implement a FIFO to record every change pro-
+ * perty request that we dispatch. In this way, when processing a
+ * property notify, we can distinguish between the notifications
+ * generated by our requests from those generated by other clients
+ * connected to the real X server.
+ */
+
+struct nxagentPropertyRec{
+ Window window;
+ Atom property;
+ struct nxagentPropertyRec *next;
+};
+
+static struct{
+ struct nxagentPropertyRec *first;
+ struct nxagentPropertyRec *last;
+ int size;
+} nxagentPropertyList = {NULL, NULL, 0};
+
+/*
+ * Removing first element from list.
+ */
+
+void nxagentRemovePropertyFromList()
+{
+ struct nxagentPropertyRec *tmp = nxagentPropertyList.first;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemovePropertyFromList: Property %ld on Window %lx to list, list size is %d.\n\n",
+ nxagentPropertyList.first -> property, nxagentPropertyList.first -> window,
+ nxagentPropertyList.size);
+ #endif
+
+ if (nxagentPropertyList.first)
+ {
+ nxagentPropertyList.first = nxagentPropertyList.first -> next;
+
+ if (--nxagentPropertyList.size == 0)
+ {
+ nxagentPropertyList.last = NULL;
+ }
+
+ free(tmp);
+ }
+}
+
+/*
+ * Add the record to the list.
+ */
+
+void nxagentAddPropertyToList(Atom property, WindowPtr pWin)
+{
+ struct nxagentPropertyRec *tmp;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return;
+ }
+
+ if ((tmp = malloc(sizeof(struct nxagentPropertyRec))) == NULL)
+ {
+ FatalError("nxagentAddPropertyToList: malloc() failed.");
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddPropertyToList: Adding record Property %ld - Window %lx[%p]"
+ "to list, list size is %d.\n", property, nxagentWindow(pWin), (void*) pWin,
+ nxagentPropertyList.size);
+ #endif
+
+ tmp -> property = property;
+ tmp -> window = nxagentWindow(pWin);
+ tmp -> next = NULL;
+
+ if (nxagentPropertyList.size == 0)
+ {
+ nxagentPropertyList.first = tmp;
+ }
+ else
+ {
+ nxagentPropertyList.last -> next = tmp;
+ }
+
+ nxagentPropertyList.last = tmp;
+ nxagentPropertyList.size++;
+}
+
+void nxagentFreePropertyList()
+{
+ while (nxagentPropertyList.size != 0)
+ {
+ nxagentRemovePropertyFromList();
+ }
+}
+
+/*
+ * We are trying to distinguish notify generated by
+ * an external client from those genarated by our
+ * own requests.
+ */
+
+Bool nxagentNotifyMatchChangeProperty(void *p)
+{
+ struct nxagentPropertyRec *first = nxagentPropertyList.first;
+ XPropertyEvent *X = p;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentNotifyMatchChangeProperty: Property notify on window %lx property %ld.\n",
+ X -> window, X -> atom);
+
+ if (first)
+ {
+ fprintf(stderr, "nxagentNotifyMatchChangeProperty: First element on list is window %lx property %ld list size is %d.\n",
+ first -> window, first -> property, nxagentPropertyList.size);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentNotifyMatchChangeProperty: List is empty.\n");
+ }
+ #endif
+
+ if (first == NULL ||
+ X -> window != first -> window ||
+ X -> atom != first -> property)
+ {
+ return False;
+ }
+
+ nxagentRemovePropertyFromList();
+
+ return True;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Rootless.h b/nx-X11/programs/Xserver/hw/nxagent/Rootless.h
new file mode 100644
index 000000000..062e164f4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Rootless.h
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Rootless_H__
+#define __Rootless_H__
+
+#include "window.h"
+
+/*
+ * The real X server's root window if we
+ * are in rootless mode.
+ */
+
+extern WindowPtr nxagentRootlessWindow;
+
+/*
+ * We want to import all properties changed by external clients to
+ * reflect properties of our internal windows but we must ignore
+ * all the property notify events generated by our own requests.
+ * For this purpose we implement a FIFO to record every change pro-
+ * perty request that we dispatch. In this way, when processing a
+ * property notify, we can distinguish between the notifications
+ * generated by our requests from those generated by other clients
+ * connected to the real X server.
+ */
+
+typedef struct
+{
+ Window window;
+ Atom property;
+} PropertyRequestRec;
+
+extern PropertyRequestRec nxagentPropertyRequests[256];
+
+Window nxagentRootlessWindowParent(WindowPtr pWin);
+
+void nxagentRootlessAddTopLevelWindow(WindowPtr pWin, Window w);
+void nxagentRootlessDelTopLevelWindow(WindowPtr pWin);
+
+WindowPtr nxagentRootlessTopLevelWindow(Window w);
+
+#ifndef _XSERVER64
+void nxagentRootlessRestack(Window *toplevel, unsigned int ntoplevel);
+#else
+void nxagentRootlessRestack(unsigned long *toplevel, unsigned int ntoplevel);
+#endif
+
+
+int nxagentExportAllProperty(WindowPtr pWin);
+
+int nxagentExportProperty(WindowPtr pWin, Atom property, Atom type, int format,
+ int mode, unsigned long nUnits, void * value);
+
+#define MAX_RETRIEVED_PROPERTY_SIZE 256 * 1024
+
+void nxagentImportProperty(Window window, Atom property, Atom type, int format,
+ unsigned long nitems, unsigned long bytes_after, unsigned char *buffer);
+
+/*
+ * Push last ChangeProperty to the list.
+ */
+
+void nxagentAddPropertyToList(Atom property, WindowPtr pWin);
+
+/*
+ * Check if a PropertyNotify match the top
+ * of the list.
+ */
+
+Bool nxagentNotifyMatchChangeProperty(void *X);
+
+void nxagentConfigureRootlessWindow(WindowPtr pWin, int x, int y, int w, int h, int bw,
+ WindowPtr pSib, int stack_mode, Mask mask);
+
+void nxagentCirculateRootlessWindows(int direction);
+
+void nxagentFreePropertyList(void);
+
+#endif /* __Rootless_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.c b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
new file mode 100644
index 000000000..1c3e76580
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.c
@@ -0,0 +1,4741 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+/*
+ * Used by the auto-disconnect feature.
+ */
+
+#include <signal.h>
+
+#include "scrnintstr.h"
+#include "dix.h"
+#include "dixstruct.h"
+#include "mi.h"
+#include "micmap.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "mipointer.h"
+#include "../../fb/fb.h"
+#include "../../randr/randrstr.h"
+#include "inputstr.h"
+#include "mivalidate.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "Extensions.h"
+#include "Atoms.h"
+#include "GCs.h"
+#include "GCOps.h"
+#include "Image.h"
+#include "Drawable.h"
+#include "Font.h"
+#include "Colormap.h"
+#include "Cursor.h"
+#include "Visual.h"
+#include "Events.h"
+#include "Init.h"
+#include "Args.h"
+#include "Client.h"
+#include "Options.h"
+#include "Splash.h"
+#include "Holder.h"
+#include "Render.h"
+#include "Trap.h"
+#include "Keyboard.h"
+#include "Pointer.h"
+#include "Reconnect.h"
+#include "Composite.h"
+#include <nx/Shadow.h>
+#include "Utils.h"
+
+#include <nx-X11/Xlib.h>
+#include "X11/include/Xinerama_nxagent.h"
+
+
+#define GC XlibGC
+#define Font XlibFont
+#define KeySym XlibKeySym
+#define XID XlibXID
+#include <nx-X11/Xlibint.h>
+#undef GC
+#undef Font
+#undef KeySym
+#undef XID
+
+#include "Xatom.h"
+#include "Xproto.h"
+
+#include "compext/Compext.h"
+
+#include "mibstorest.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#undef PANIC
+#undef WARNING
+#undef TEST
+#undef DEBUG
+#undef WATCH
+#undef DUMP
+
+/*
+ * Display a pixmap on an shadow
+ * display used for debug.
+ */
+
+#ifdef DUMP
+
+void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height);
+
+void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width,
+ int height, int xDst, int yDst)
+#endif
+
+#ifdef WATCH
+#include "unistd.h"
+#endif
+
+extern Bool nxagentIpaq;
+extern Pixmap nxagentIconPixmap;
+extern Pixmap nxagentIconShape;
+extern Bool useXpmIcon;
+
+Window nxagentDefaultWindows[MAXSCREENS];
+Window nxagentInputWindows[MAXSCREENS];
+Window nxagentScreenSaverWindows[MAXSCREENS];
+
+#ifdef NXAGENT_ONSTART
+Atom nxagentWMStart;
+Window nxagentSplashWindow = None;
+Pixmap nxagentPixmapLogo;
+#endif
+
+ScreenPtr nxagentDefaultScreen = NULL;
+int nxagentArgc = 0;
+char **nxagentArgv = NULL;
+
+#ifdef NXAGENT_ARTSD
+
+char mcop_atom[] = "MCOPGLOBALS";
+Atom mcop_local_atom = None;
+unsigned char fromHexNibble(char c);
+void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port);
+
+#endif
+
+Window nxagentIconWindow = None;
+Window nxagentFullscreenWindow = None;
+
+#ifdef VIEWPORT_FRAME
+
+WindowPtr nxagentViewportFrameLeft;
+WindowPtr nxagentViewportFrameRight;
+WindowPtr nxagentViewportFrameAbove;
+WindowPtr nxagentViewportFrameBelow;
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+Bool nxagentCreateScreenResources(ScreenPtr pScreen);
+void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix);
+
+
+/*
+ * These variables are for shadowing feature.
+ */
+
+int nxagentShadowResize = 0;
+
+WindowPtr nxagentShadowWindowPtr = NULL;
+
+static XID accessPixmapID;
+static Window accessWindowID;
+static int imageByteOrder;
+static unsigned char nxagentMasterDepth;
+static unsigned char nxagentCheckDepth = 0;
+static unsigned int nxagentBppShadow;
+static unsigned int nxagentBppMaster;
+int nxagentShadowXConnectionNumber;
+GCPtr nxagentShadowGCPtr = NULL;
+PixmapPtr nxagentShadowPixmapPtr = NULL;
+char * nxagentShadowBuffer;
+unsigned char nxagentShadowDepth;
+int nxagentShadowWidth;
+int nxagentShadowHeight;
+Display * nxagentShadowDisplay;
+short nxagentShadowUid = -1;
+
+void nxagentShadowAdaptDepth(unsigned int, unsigned int, unsigned int, char **);
+
+RegionRec nxagentShadowUpdateRegion;
+
+#define NXAGENT_DEFAULT_DPI 75
+
+/*
+ * From randr/randr.c. This was originally static
+ * but we need it here.
+ */
+
+int TellChanged(WindowPtr pWin, void * value);
+
+int nxagentBitsPerPixel(int depth)
+{
+ if (depth == 1) return 1;
+ else if (depth <= 8) return 8;
+ else if (depth <= 16) return 16;
+ else return 32;
+}
+
+void nxagentSetScreenInfo(ScreenInfo *screenInfo)
+{
+ /*
+ * Setup global screen info parameters. In the Xnest
+ * server this stuff is done after having opened the
+ * real display as Xnest lets the screen reflect the
+ * order of the remote end. Agent will instead set
+ * the order according to local endianess and swap
+ * data whenever it is appropriate.
+ *
+ * From a standard implementation:
+ *
+ * screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ * screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ * screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ * screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ *
+ * From Xnest implementation:
+ *
+ * screenInfo -> imageByteOrder = ImageByteOrder(nxagentDisplay);
+ * screenInfo -> bitmapScanlineUnit = BitmapUnit(nxagentDisplay);
+ * screenInfo -> bitmapScanlinePad = BitmapPad(nxagentDisplay);
+ * screenInfo -> bitmapBitOrder = BitmapBitOrder(nxagentDisplay);
+ */
+
+ screenInfo -> imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo -> bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo -> bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo -> bitmapBitOrder = BITMAP_BIT_ORDER;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenInfo: Server image order is [%d] bitmap order is [%d].\n",
+ screenInfo -> imageByteOrder, screenInfo -> bitmapBitOrder);
+
+ fprintf(stderr, "nxagentSetScreenInfo: Server scanline unit is [%d] scanline pad is [%d].\n",
+ screenInfo -> bitmapScanlineUnit, screenInfo -> bitmapScanlinePad);
+ #endif
+}
+
+void nxagentSetPixmapFormats(ScreenInfo *screenInfo)
+{
+ int i;
+
+ /*
+ * Formats are created with no care of which are supported
+ * on the real display. Creating only formats supported
+ * by the remote end makes troublesome handling migration
+ * of session from a display to another.
+ */
+
+ screenInfo -> numPixmapFormats = nxagentNumPixmapFormats;
+
+ for (i = 0; i < nxagentNumPixmapFormats; i++)
+ {
+ screenInfo -> formats[i].depth = nxagentPixmapFormats[i].depth;
+ screenInfo -> formats[i].bitsPerPixel = nxagentPixmapFormats[i].bits_per_pixel;
+ screenInfo -> formats[i].scanlinePad = nxagentPixmapFormats[i].scanline_pad;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetPixmapFormats: Set format at index [%d] to depth [%d] "
+ "bits per pixel [%d] scanline pad [%d].\n", i,
+ screenInfo -> formats[i].depth, screenInfo -> formats[i].bitsPerPixel,
+ screenInfo -> formats[i].scanlinePad);
+ #endif
+ }
+}
+
+void nxagentMinimizeFromFullScreen(ScreenPtr pScreen)
+{
+ XUnmapWindow(nxagentDisplay, nxagentFullscreenWindow);
+
+ if (nxagentIpaq)
+ {
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+ }
+ else
+ {
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+ }
+}
+
+void nxagentMaximizeToFullScreen(ScreenPtr pScreen)
+{
+ if (nxagentIpaq)
+ {
+ XUnmapWindow(nxagentDisplay, nxagentIconWindow);
+
+ XMapWindow(nxagentDisplay, nxagentFullscreenWindow);
+ }
+ else
+ {
+/*
+ XUnmapWindow(nxagentDisplay, nxagentIconWindow);
+*/
+/*
+FIXME: We'll check for ReparentNotify and LeaveNotify events after XReparentWindow()
+ in order to avoid the session window is iconified.
+ We could avoid the sesssion window is iconified when a LeaveNotify event is received,
+ so this check would be unnecessary.
+*/
+ struct timeval timeout;
+ int i;
+ XEvent e;
+
+ XReparentWindow(nxagentDisplay, nxagentFullscreenWindow,
+ RootWindow(nxagentDisplay, DefaultScreen(nxagentDisplay)), 0, 0);
+
+ for (i = 0; i < 100 && nxagentWMIsRunning; i++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMaximizeToFullscreen: WARNING! Going to wait for the ReparentNotify event.\n");
+ #endif
+
+ if (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, ReparentNotify, &e))
+ {
+ break;
+ }
+
+ XSync(nxagentDisplay, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50 * 1000;
+
+ nxagentWaitEvents(nxagentDisplay, &timeout);
+ }
+
+ XMapRaised(nxagentDisplay, nxagentFullscreenWindow);
+
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+
+ while (XCheckTypedWindowEvent(nxagentDisplay, nxagentFullscreenWindow, LeaveNotify, &e));
+/*
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+*/
+ }
+}
+
+Window nxagentCreateIconWindow()
+{
+ XSetWindowAttributes attributes;
+ unsigned long valuemask;
+ char* window_name;
+ XTextProperty windowName;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ Window w;
+ Mask mask;
+
+ /*
+ * Create icon window.
+ */
+
+ attributes.override_redirect = False;
+ attributes.colormap = DefaultColormap(nxagentDisplay, DefaultScreen(nxagentDisplay));
+ attributes.background_pixmap = nxagentScreenSaverPixmap;
+ valuemask = CWOverrideRedirect | CWBackPixmap | CWColormap;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateIconWindow: Going to create new icon window.\n");
+ #endif
+
+ w = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ 0, 0, 1, 1, 0,
+ DefaultDepth(nxagentDisplay, DefaultScreen(nxagentDisplay)),
+ InputOutput,
+ DefaultVisual(nxagentDisplay, DefaultScreen(nxagentDisplay)),
+ valuemask, &attributes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateIconWindow: Created new icon window with id [%lu].\n",
+ (long unsigned int)nxagentIconWindow);
+ #endif
+
+ /*
+ * Set hints to the window manager for the icon window.
+ */
+
+ window_name = nxagentWindowName;
+ XStringListToTextProperty(&window_name, 1, &windowName);
+ sizeHints.flags = PMinSize | PMaxSize;
+ sizeHints.min_width = sizeHints.max_width = 1;
+ sizeHints.min_height = sizeHints.max_height = 1;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ wmHints.initial_state = IconicState;
+ wmHints.icon_pixmap = nxagentIconPixmap;
+
+ if (useXpmIcon)
+ {
+ wmHints.icon_mask = nxagentIconShape;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ }
+ else
+ {
+ wmHints.flags = StateHint | IconPixmapHint;
+ }
+
+ XSetWMProperties(nxagentDisplay, w,
+ &windowName, &windowName,
+ NULL , 0 , &sizeHints, &wmHints, NULL);
+
+ /*
+ * Enable events from the icon window.
+ */
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, w, (mask & ~(KeyPressMask |
+ KeyReleaseMask)) | StructureNotifyMask);
+
+ /*
+ * Notify to client if user closes icon window.
+ */
+
+ if (nxagentWMIsRunning && !nxagentOption(Rootless))
+ {
+ XlibAtom deleteWMAtom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */
+
+ XSetWMProtocols(nxagentDisplay, w, &deleteWMAtom, 1);
+ }
+
+ return w;
+}
+
+Bool nxagentMagicPixelZone(int x, int y)
+{
+ return (x >= nxagentOption(Width) - 1 && y < 1);
+}
+
+void nxagentSetScreenSaverTime(void)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime was [%lu], ScreenSaverInterval was [%lu].\n",
+ (long unsigned int)ScreenSaverTime, (long unsigned int)ScreenSaverInterval);
+ #endif
+
+ /*
+ * More than one timeout could be used here,
+ * to make use of screen-saver handler not
+ * only for the timeout feature. In a case
+ * like this, the lower timeout have to be
+ * used as ScreenSaverTime.
+ */
+
+ if (nxagentAutoDisconnectTimeout > 0)
+ {
+ ScreenSaverTime = nxagentAutoDisconnectTimeout;
+ }
+
+ ScreenSaverInterval = ScreenSaverTime;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetScreenSaverTime: ScreenSaverTime now is [%lu], ScreenSaverInterval now is [%lu].\n",
+ (long unsigned int)ScreenSaverTime, (long unsigned int)ScreenSaverInterval);
+ #endif
+}
+
+static Bool nxagentSaveScreen(ScreenPtr pScreen, int what)
+{
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Called for screen at [%p] with parameter [%d].\n",
+ (void *) pScreen, what);
+
+ fprintf(stderr, "nxagentSaveScreen: SCREEN_SAVER_ON is [%d] SCREEN_SAVER_OFF is [%d] "
+ "SCREEN_SAVER_FORCER is [%d] SCREEN_SAVER_CYCLE is [%d].\n",
+ SCREEN_SAVER_ON, SCREEN_SAVER_OFF, SCREEN_SAVER_FORCER,
+ SCREEN_SAVER_CYCLE);
+ #endif
+
+ /*
+ * We need only to reset the timeouts
+ * in this case.
+ */
+
+ if (what == SCREEN_SAVER_OFF)
+ {
+ nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND;
+
+ return 1;
+ }
+
+ /*
+ * The lastDeviceEventTime is updated every time
+ * a device event is received, and it is used by
+ * WaitForSomething() to know when the SaveScreens()
+ * function should be called. This solution doesn't
+ * take care of a pointer button not released, so
+ * we have to handle this case by ourselves.
+ */
+
+/*
+FIXME: Do we need to check the key grab if the
+ autorepeat feature is disabled?
+*/
+ if (inputInfo.pointer -> button -> buttonsDown > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Ignoring timeout, there is a pointer button down.\n");
+ #endif
+
+ /*
+ * Returning 0 the SaveScreens() function
+ * (which calls this one) tries to build
+ * a screen-saver creating a new window.
+ * We don't want this, so we return 1 in
+ * any case.
+ */
+
+ return 1;
+ }
+
+ /*
+ * Handling the auto-disconnect feature.
+ * If there is any client attached and the persisten-
+ * ce is allowed then leave the session running, else
+ * terminate it. It should use something less brutal,
+ * though raising a signal should ensure that the code
+ * follows the usual execution path.
+ */
+
+ if (nxagentOption(Timeout) > 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout was [%d].\n",
+ nxagentAutoDisconnectTimeout);
+ #endif
+
+ nxagentAutoDisconnectTimeout -= ScreenSaverTime;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSaveScreen: Auto-disconnect timeout is [%d].\n",
+ nxagentAutoDisconnectTimeout);
+ #endif
+
+ if (nxagentSessionState == SESSION_UP &&
+ nxagentAutoDisconnectTimeout <= 0)
+ {
+ nxagentAutoDisconnectTimeout = nxagentOption(Timeout) * MILLI_PER_SECOND;
+
+ if (nxagentClients == 0)
+ {
+ fprintf(stderr, "Info: Terminating session with no client running.\n");
+
+ raise(SIGTERM);
+ }
+ else if (nxagentOption(Persistent) == 0)
+ {
+ fprintf(stderr, "Info: Terminating session with persistence not allowed.\n");
+
+ raise(SIGTERM);
+ }
+ else
+ {
+ fprintf(stderr, "Info: Suspending session with %d clients running.\n",
+ nxagentClients);
+
+ raise(SIGHUP);
+ }
+ }
+ }
+
+ return 1;
+}
+
+Bool nxagentCreateScreenResources(ScreenPtr pScreen)
+{
+ Bool ret;
+
+ CreatePixmapProcPtr savedCreatePixmap = pScreen->CreatePixmap;
+ ModifyPixmapHeaderProcPtr savedModifyPixmapHeader = pScreen->ModifyPixmapHeader;
+
+ pScreen->CreatePixmap = fbCreatePixmap;
+ pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
+ ret = miCreateScreenResources(pScreen);
+
+ pScreen->CreatePixmap = savedCreatePixmap;
+ pScreen->ModifyPixmapHeader = savedModifyPixmapHeader;
+
+ return ret;
+}
+
+static Bool nxagentCursorOffScreen(ScreenPtr *pPtrScreen, int *x, int *y)
+{
+ return False;
+}
+
+static void nxagentCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+}
+
+static miPointerScreenFuncRec nxagentPointerCursorFuncs =
+{
+ nxagentCursorOffScreen,
+ nxagentCrossScreen,
+ miPointerWarpCursor
+};
+
+#ifdef VIEWPORT_FRAME
+
+void nxagentInitViewportFrame(ScreenPtr pScreen, WindowPtr pRootWin)
+{
+ int error = Success;
+ VisualID visual = 0;
+ int i;
+ XID xid;
+
+ if (nxagentOption(Rootless))
+ {
+ return;
+ }
+
+ for (i = 0; i < pScreen -> numDepths; i++)
+ {
+ if (pScreen -> allowedDepths[i].depth == pRootWin -> drawable.depth)
+ {
+ visual = pScreen -> allowedDepths[i].vids[0];
+ break;
+ }
+ }
+
+ /*
+ * It is not necessary create the windows on the real X server. But this
+ * windows are not visible. Create them it is not a great effort, and avoids
+ * many errors.
+ *
+ * nxagentScreenTrap = True;
+ */
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameLeft = CreateWindow(xid, pRootWin, -NXAGENT_FRAME_WIDTH, 0, NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.height,
+ 0, InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual, &error);
+
+ AddResource(xid, RT_WINDOW, (void *) nxagentViewportFrameLeft);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameLeft.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameRight = CreateWindow(xid, pRootWin, pRootWin -> drawable.width, 0,
+ NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.height,
+ 0, InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual,
+ &error);
+
+ AddResource(xid, RT_WINDOW, (void *) nxagentViewportFrameRight);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameRight.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameAbove = CreateWindow(xid, pRootWin, 0, -NXAGENT_FRAME_WIDTH,
+ pRootWin -> drawable.width,
+ NXAGENT_FRAME_WIDTH, 0,
+ InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual,
+ &error);
+
+ AddResource(xid, RT_WINDOW, (void *) nxagentViewportFrameAbove);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameAbove.\n");
+ #endif
+
+ error = Success;
+ }
+
+ xid = FakeClientID(serverClient -> index);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitViewportFrame: XID = [%lx]\n", xid);
+ #endif
+
+ nxagentViewportFrameBelow = CreateWindow(xid, pRootWin, 0,
+ pRootWin -> drawable.height,
+ pRootWin -> drawable.width,
+ NXAGENT_FRAME_WIDTH, 0,
+ InputOutput, 0, NULL,
+ pRootWin -> drawable.depth,
+ serverClient, visual, &error);
+
+ AddResource(xid, RT_WINDOW, (void *) nxagentViewportFrameBelow);
+
+ if (error != Success)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentInitViewportFrame: Error creating nxagentViewportFrameBelow.\n");
+ #endif
+ }
+
+ nxagentViewportFrameLeft -> overrideRedirect = 1;
+ nxagentViewportFrameRight -> overrideRedirect = 1;
+ nxagentViewportFrameAbove -> overrideRedirect = 1;
+ nxagentViewportFrameBelow -> overrideRedirect = 1;
+
+ MapWindow(nxagentViewportFrameLeft, serverClient);
+ MapWindow(nxagentViewportFrameRight, serverClient);
+ MapWindow(nxagentViewportFrameAbove, serverClient);
+ MapWindow(nxagentViewportFrameBelow, serverClient);
+
+ /*
+ * nxagentScreenTrap = False;
+ */
+}
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+void nxagentPrintAgentGeometry(char *hdrMessage, char *prefix)
+{
+ #ifdef WARNING
+
+ if (prefix == NULL)
+ {
+ prefix = "";
+ }
+
+ if (hdrMessage)
+ {
+ fprintf(stderr, "--------------- %s -----------------.\n", hdrMessage);
+ }
+
+ fprintf(stderr, "%s Root window at offset (%d,%d) size (%d,%d).\n", prefix,
+ nxagentOption(RootX), nxagentOption(RootY),
+ nxagentOption(RootWidth), nxagentOption(RootHeight));
+
+ fprintf(stderr, "%s Default window at offset (%d,%d) size (%d,%d) border size %d.\n", prefix,
+ nxagentOption(X), nxagentOption(Y), nxagentOption(Width), nxagentOption(Height),
+ nxagentOption(BorderWidth));
+
+ fprintf(stderr, "%s Span between root window and default window is (%d,%d).\n", prefix,
+ nxagentOption(ViewportXSpan), nxagentOption(ViewportYSpan));
+
+ fprintf(stderr, "%s Default window in window mode has offset (%d,%d) and size (%d,%d).\n", prefix,
+ nxagentOption(SavedX), nxagentOption(SavedY), nxagentOption(SavedWidth), nxagentOption(SavedHeight));
+
+ fprintf(stderr, "%s Fullscreen is %s.\n", prefix,
+ nxagentOption(Fullscreen) ? "ON" : "OFF");
+
+ fprintf(stderr, "%s Desktop resize mode is %s.\n", prefix,
+ nxagentOption(DesktopResize) ? "ON" : "OFF");
+
+ fprintf(stderr, "%s Resize desktop at startup is %s.\n", prefix,
+ nxagentResizeDesktopAtStartup ? "ON" : "OFF");
+
+ #endif
+}
+
+static int nxagentColorOffset(unsigned long mask)
+{
+ int count;
+
+ for (count = 0; !(mask & 1) && count < 32; count++)
+ {
+ mask >>= 1;
+ }
+
+ return count;
+}
+
+Bool nxagentOpenScreen(ScreenPtr pScreen,
+ int argc, char *argv[])
+{
+ VisualPtr visuals;
+ DepthPtr depths;
+ int numVisuals, numDepths;
+ int i, j, depthIndex;
+ unsigned long valuemask;
+ XSetWindowAttributes attributes;
+ XWindowAttributes gattributes;
+ XSizeHints sizeHints;
+ XWMHints wmHints;
+ Mask mask;
+ Bool resetAgentPosition = False;
+
+ VisualID defaultVisual;
+ int rootDepth;
+
+ void * pFrameBufferBits;
+ int bitsPerPixel;
+ int sizeInBytes;
+
+ int defaultVisualIndex = 0;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Called for screen index [%d].\n",
+ pScreen->myNum);
+ #endif
+
+ if (nxagentRenderEnable && nxagentReconnectTrap == False)
+ {
+ PictureScreenPrivateIndex = -1;
+ }
+
+ nxagentDefaultScreen = pScreen;
+
+ nxagentQueryAtoms(pScreen);
+
+ #ifdef NXAGENT_ONSTART
+ nxagentWMStart = nxagentAtoms[3]; /* WM_NX_READY */
+ #endif
+
+ /*
+ * Forced geometry parameter
+ * to user geometry.
+ */
+
+ if (nxagentResizeDesktopAtStartup)
+ {
+ if (nxagentUserGeometry.flag & XValue)
+ {
+ nxagentChangeOption(X, nxagentUserGeometry.X);
+ }
+
+ if (nxagentUserGeometry.flag & YValue)
+ {
+ nxagentChangeOption(Y, nxagentUserGeometry.Y);
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue)
+ {
+ nxagentChangeOption(Width, nxagentUserGeometry.Width);
+ nxagentChangeOption(RootWidth, nxagentUserGeometry.Width);
+
+ if (nxagentOption(SavedWidth) > nxagentUserGeometry.Width)
+ {
+ nxagentChangeOption(SavedWidth, nxagentUserGeometry.Width);
+ }
+ }
+
+ if (nxagentUserGeometry.flag & HeightValue)
+ {
+ nxagentChangeOption(Height, nxagentUserGeometry.Height);
+ nxagentChangeOption(RootHeight, nxagentUserGeometry.Height);
+
+ if (nxagentOption(SavedHeight) > nxagentUserGeometry.Height)
+ {
+ nxagentChangeOption(SavedHeight, nxagentUserGeometry.Height);
+ }
+ }
+ }
+
+ /*
+ * This is first time the
+ * screen is initialized.
+ * Filling the geometry parameter
+ * from user geometry.
+ */
+
+ if (nxagentReconnectTrap == False)
+ {
+ if (nxagentUserGeometry.flag & XValue)
+ {
+ nxagentChangeOption(X, nxagentUserGeometry.X);
+ }
+
+ if (nxagentUserGeometry.flag & YValue)
+ {
+ nxagentChangeOption(Y, nxagentUserGeometry.Y);
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue)
+ {
+ nxagentChangeOption(RootWidth, nxagentUserGeometry.Width);
+ }
+
+ if (nxagentUserGeometry.flag & HeightValue)
+ {
+ nxagentChangeOption(RootHeight, nxagentUserGeometry.Height);
+ }
+ }
+ else if (nxagentWMIsRunning && !nxagentOption(Rootless) && !nxagentOption(Fullscreen))
+ {
+ /*
+ * At reconnection, try to estimate the shift due to WM reparenting.
+ */
+
+ if (nxagentOption(X) >= 6)
+ {
+ nxagentChangeOption(X, nxagentOption(X) - 6);
+ }
+
+ if (nxagentOption(Y) >= 25)
+ {
+ nxagentChangeOption(Y, nxagentOption(Y) - 25);
+ }
+ }
+
+ /*
+ * Determine the size of the root window.
+ * It is the maximum size of the screen
+ * if we are either in rootless or in
+ * fullscreen mode.
+ */
+
+ if (nxagentOption(Rootless) == False && nxagentWMIsRunning == False)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Forcing fullscreen mode with no window manager running.\n");
+ #endif
+
+ nxagentChangeOption(Fullscreen, True);
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt &&
+ (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup))
+ {
+ NXSetExposeParameters(nxagentDisplay, 0, 0, 0);
+ }
+ }
+
+ if (nxagentOption(Fullscreen) &&
+ nxagentWMIsRunning &&
+ nxagentReconnectTrap &&
+ nxagentResizeDesktopAtStartup == False &&
+ nxagentXServerGeometryChanged())
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Forcing window mode with server geometry changed.\n");
+ #endif
+
+ nxagentChangeOption(Fullscreen, False);
+
+ nxagentChangeOption(AllScreens, False);
+
+ nxagentFullscreenWindow = 0;
+
+ resetAgentPosition = True;
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(X, 0);
+ nxagentChangeOption(Y, 0);
+
+ nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+
+ nxagentChangeOption(BorderWidth, 0);
+
+ if (nxagentReconnectTrap == False || nxagentResizeDesktopAtStartup)
+ {
+ nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+
+ if (nxagentOption(RootWidth) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(SavedWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+ else
+ {
+ nxagentChangeOption(SavedWidth, nxagentOption(RootWidth));
+ }
+
+ if (nxagentOption(RootHeight) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(SavedHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+ else
+ {
+ nxagentChangeOption(SavedHeight, nxagentOption(RootHeight));
+ }
+ }
+
+ nxagentChangeOption(RootX, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(RootWidth)) / 2));
+ nxagentChangeOption(RootY, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(RootHeight)) / 2));
+ }
+ else
+ {
+ nxagentChangeOption(BorderWidth, 0);
+
+ if (nxagentReconnectTrap == False)
+ {
+ nxagentChangeOption(RootX, 0);
+ nxagentChangeOption(RootY, 0);
+
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+
+ /*
+ * Be sure that the agent window won't be bigger
+ * than the root window.
+ */
+
+ if (nxagentOption(Width) > nxagentOption(RootWidth))
+ {
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ }
+
+ if (nxagentOption(Height) > nxagentOption(RootHeight))
+ {
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+
+ /*
+ * Be sure that the agent window won't be bigger
+ * than the X server root window.
+ */
+
+ if (nxagentOption(Width) > WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+
+ if (nxagentOption(Height) > HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)))
+ {
+ nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 3 / 4);
+ }
+
+ /*
+ * Forcing the agent window geometry to be equal to
+ * the root window geometry the first time the
+ * screen is initialized if the geometry hasn't been
+ * esplicitly set in the option file and if
+ * the root window isn't bigger than the X server
+ * root window..
+ */
+
+ if (nxagentReconnectTrap == False)
+ {
+ if ((nxagentOption(RootWidth) < WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) &&
+ !(nxagentUserGeometry.flag & WidthValue))
+ {
+ nxagentChangeOption(Width, nxagentOption(RootWidth));
+ }
+
+ if ((nxagentOption(RootHeight) < HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay))) &&
+ !(nxagentUserGeometry.flag & HeightValue))
+ {
+ nxagentChangeOption(Height, nxagentOption(RootHeight));
+ }
+ }
+
+ if (resetAgentPosition)
+ {
+ nxagentChangeOption(X, ((WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(Width)) / 2));
+
+ nxagentChangeOption(Y, ((HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) -
+ nxagentOption(Height)) / 2));
+ }
+
+ nxagentChangeOption(SavedWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedHeight, nxagentOption(RootHeight));
+ }
+
+ if (nxagentOption(Rootless))
+ {
+ nxagentChangeOption(RootWidth, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(RootHeight, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ }
+
+ nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
+
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ if (nxagentReconnectTrap == 0)
+ {
+ if (nxagentOption(Persistent))
+ {
+ nxagentArgc = argc;
+ nxagentArgv = argv;
+ }
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "Screen: going to open screen, time is [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+
+ #endif
+
+ /*
+ * Initialize all our privates.
+ */
+
+ if (AllocateWindowPrivate(pScreen, nxagentWindowPrivateIndex, sizeof(nxagentPrivWindowRec)) == 0 ||
+ AllocateGCPrivate(pScreen, nxagentGCPrivateIndex, sizeof(nxagentPrivGC)) == 0 ||
+ AllocateClientPrivate(nxagentClientPrivateIndex, sizeof(PrivClientRec)) == 0 ||
+ AllocatePixmapPrivate(pScreen, nxagentPixmapPrivateIndex, sizeof(nxagentPrivPixmapRec)) == 0)
+ {
+ return False;
+ }
+
+ /*
+ * Initialize the depths.
+ */
+
+ depths = (DepthPtr) malloc(nxagentNumDepths * sizeof(DepthRec));
+
+ for (i = 0; i < nxagentNumDepths; i++)
+ {
+ depths[i].depth = nxagentDepths[i];
+ depths[i].numVids = 0;
+ depths[i].vids = (VisualID *) malloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
+ }
+
+ /*
+ * Initialize the visuals.
+ */
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Setting up visuals. Original array has size "
+ "[%d].\n", nxagentNumVisuals);
+ #endif
+
+ numVisuals = 0;
+ numDepths = nxagentNumDepths;
+
+ visuals = (VisualPtr) malloc(nxagentNumVisuals * sizeof(VisualRec));
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ visuals[numVisuals].vid = FakeClientID(0);
+ visuals[numVisuals].class = nxagentVisuals[i].class;
+ visuals[numVisuals].bitsPerRGBValue = nxagentVisuals[i].bits_per_rgb;
+ visuals[numVisuals].ColormapEntries = nxagentVisuals[i].colormap_size;
+ visuals[numVisuals].nplanes = nxagentVisuals[i].depth;
+ visuals[numVisuals].redMask = nxagentVisuals[i].red_mask;
+ visuals[numVisuals].greenMask = nxagentVisuals[i].green_mask;
+ visuals[numVisuals].blueMask = nxagentVisuals[i].blue_mask;
+ visuals[numVisuals].offsetRed = nxagentColorOffset(nxagentVisuals[i].red_mask);
+ visuals[numVisuals].offsetGreen = nxagentColorOffset(nxagentVisuals[i].green_mask);
+ visuals[numVisuals].offsetBlue = nxagentColorOffset(nxagentVisuals[i].blue_mask);
+
+ /*
+ * Check for and remove the duplicates.
+ */
+
+ if (i == nxagentDefaultVisualIndex)
+ {
+ defaultVisualIndex = numVisuals;
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Set default visual index [%d].\n" ,
+ defaultVisualIndex);
+ #endif
+ }
+ else
+ {
+ for (j = 0; j < numVisuals; j++)
+ {
+ if (visuals[numVisuals].class == visuals[j].class &&
+ visuals[numVisuals].bitsPerRGBValue ==
+ visuals[j].bitsPerRGBValue &&
+ visuals[numVisuals].ColormapEntries ==
+ visuals[j].ColormapEntries &&
+ visuals[numVisuals].nplanes == visuals[j].nplanes &&
+ visuals[numVisuals].redMask == visuals[j].redMask &&
+ visuals[numVisuals].greenMask == visuals[j].greenMask &&
+ visuals[numVisuals].blueMask == visuals[j].blueMask &&
+ visuals[numVisuals].offsetRed == visuals[j].offsetRed &&
+ visuals[numVisuals].offsetGreen == visuals[j].offsetGreen &&
+ visuals[numVisuals].offsetBlue == visuals[j].offsetBlue)
+ break;
+ }
+
+ if (j < numVisuals)
+ continue;
+
+ }
+
+ depthIndex = UNDEFINED;
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Added visual [%lu].\n" ,
+ (long unsigned int)visuals[numVisuals].vid);
+ #endif
+
+ for (j = 0; j < numDepths; j++)
+ {
+ if (depths[j].depth == nxagentVisuals[i].depth)
+ {
+ depthIndex = j;
+ break;
+ }
+ }
+
+ if (depthIndex == UNDEFINED)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentOpenScreen: WARNING! Can't find a matching depth for visual depth [%d].\n",
+ nxagentVisuals[i].depth);
+ #endif
+
+ depthIndex = numDepths;
+
+ depths[depthIndex].depth = nxagentVisuals[i].depth;
+ depths[depthIndex].numVids = 0;
+ depths[depthIndex].vids = (VisualID *) malloc(MAXVISUALSPERDEPTH * sizeof(VisualID));
+
+ numDepths++;
+ }
+
+ if (depths[depthIndex].numVids >= MAXVISUALSPERDEPTH)
+ {
+ FatalError("Visual table overflow");
+ }
+
+ depths[depthIndex].vids[depths[depthIndex].numVids] = visuals[numVisuals].vid;
+
+ depths[depthIndex].numVids++;
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Registered visual [%lu] for depth [%d (%d)].\n" ,
+ (long unsigned int)visuals[numVisuals].vid, depthIndex,
+ depths[depthIndex].depth);
+ #endif
+
+ numVisuals++;
+ }
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "Debug: Setting default visual [%d (%lu)].\n",
+ defaultVisualIndex, (long unsigned int)visuals[defaultVisualIndex].vid);
+
+ fprintf(stderr, "Debug: Setting root depth [%d].\n",
+ visuals[defaultVisualIndex].nplanes);
+ #endif
+
+ defaultVisual = visuals[defaultVisualIndex].vid;
+ rootDepth = visuals[defaultVisualIndex].nplanes;
+
+ nxagentInitAlphaVisual();
+
+ bitsPerPixel = nxagentBitsPerPixel(rootDepth);
+
+ if (bitsPerPixel == 1)
+ {
+ sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight);
+ }
+ else
+ {
+ sizeInBytes = PixmapBytePad(nxagentOption(RootWidth), rootDepth) * nxagentOption(RootHeight) * bitsPerPixel/8;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Frame buffer allocated. rootDepth "
+ "[%d] bitsPerPixel [%d] sizeInBytes [%d]\n", rootDepth, bitsPerPixel, sizeInBytes);
+ #endif
+
+ pFrameBufferBits = (char *) malloc(sizeInBytes);
+
+ if (!pFrameBufferBits)
+ {
+ return FALSE;
+ }
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "nxagentOpenScreen: Before fbScreenInit numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%lu].\n", numVisuals, numDepths,
+ rootDepth, (long unsigned int)defaultVisual);
+ #endif
+
+ if (monitorResolution < 1)
+ {
+ monitorResolution = NXAGENT_DEFAULT_DPI;
+ }
+
+ if (!fbScreenInit(pScreen, pFrameBufferBits, nxagentOption(RootWidth), nxagentOption(RootHeight),
+ monitorResolution, monitorResolution, PixmapBytePad(nxagentOption(RootWidth), rootDepth), bitsPerPixel))
+ {
+ return FALSE;
+ }
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "nxagentOpenScreen: After fbScreenInit numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%lu].\n", numVisuals, numDepths,
+ rootDepth, (long unsigned int)defaultVisual);
+ #endif
+
+ /*
+ * Complete the initialization of the GLX
+ * extension. This will add the GLX visuals
+ * and will modify numVisuals and numDepths.
+ */
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "nxagentOpenScreen: Before GLX numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%lu].\n", numVisuals, numDepths,
+ rootDepth, (long unsigned int)defaultVisual);
+ #endif
+
+ nxagentInitGlxExtension(&visuals, &depths, &numVisuals, &numDepths,
+ &rootDepth, &defaultVisual);
+
+ #if defined(DEBUG) || defined(DEBUG_COLORMAP)
+ fprintf(stderr, "nxagentOpenScreen: After GLX numVisuals [%d] numDepths [%d] "
+ "rootDepth [%d] defaultVisual [%lu].\n", numVisuals, numDepths,
+ rootDepth, (long unsigned int)defaultVisual);
+ #endif
+
+ /*
+ * Replace the visuals and depths initialized
+ * by fbScreenInit with our own.
+ */
+
+ free(pScreen -> visuals);
+ free(pScreen -> allowedDepths);
+
+ pScreen -> visuals = visuals;
+ pScreen -> allowedDepths = depths;
+ pScreen -> numVisuals = numVisuals;
+ pScreen -> numDepths = numDepths;
+ pScreen -> rootVisual = defaultVisual;
+ pScreen -> rootDepth = rootDepth;
+
+ /*
+ * Complete the initialization of the RANDR
+ * extension.
+ */
+
+ nxagentInitRandRExtension(pScreen);
+
+ /*
+ * Set up the internal structures used for
+ * tracking the proxy resources associated
+ * to the unpack and split operations.
+ */
+
+ nxagentInitSplitResources();
+ nxagentInitUnpackResources();
+
+ /*
+ * Initializing the pixmaps that will serve as
+ * "placeholders" in lazy encoding. We need one
+ * pixmap for each depth.
+ */
+
+ for (i = 0; i < numDepths; i++)
+ {
+ nxagentMarkPlaceholderNotLoaded(i);
+ }
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenScreen: Watchpoint 7.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+N/A
+*/
+
+ sleep(30);
+
+ #endif
+
+ if (nxagentParentWindow != 0)
+ {
+ /*
+ * This would cause a GetWindowAttributes
+ * and a GetGeometry (asynchronous) reply.
+ */
+
+ XGetWindowAttributes(nxagentDisplay, nxagentParentWindow, &gattributes);
+
+ nxagentChangeOption(Width, gattributes.width);
+ nxagentChangeOption(Height, gattributes.height);
+ }
+
+ if (nxagentOption(AllScreens))
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ /*
+ * We need to disable the host's screensaver or
+ * it will otherwise grab the screen even if it
+ * is under agent's control.
+ */
+
+ XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
+ }
+
+ if (nxagentTrue24)
+ {
+ fbGetScreenPrivate(pScreen) -> win32bpp = visuals[nxagentDefaultVisualIndex].nplanes;
+ fbGetScreenPrivate(pScreen) -> pix32bpp = visuals[nxagentDefaultVisualIndex].nplanes;
+ }
+ else
+ {
+ fbGetScreenPrivate(pScreen) -> win32bpp = 32;
+ fbGetScreenPrivate(pScreen) -> pix32bpp = 32;
+ }
+
+ /*
+ * We call miScreenInit with NULL in place of the screen area if we
+ * don't want to initialize the frame buffer.
+ *
+ * if (!miScreenInit(pScreen, NULL, nxagentOption(RootWidth),
+ * nxagentOption(RootHeight), 1, 1, nxagentOption(RootWidth),
+ * visuals[nxagentDefaultVisualIndex].nplanes, / * Root depth. * /
+ * numDepths, depths,
+ * visuals[nxagentDefaultVisualIndex].vid,* Root visual. * /
+ * numVisuals, visuals))
+ * return FALSE;
+ */
+
+ pScreen->defColormap = (Colormap) FakeClientID(0);
+ pScreen->minInstalledCmaps = MINCMAPS;
+ pScreen->maxInstalledCmaps = MAXCMAPS;
+
+ pScreen->whitePixel = nxagentWhitePixel;
+ pScreen->blackPixel = nxagentBlackPixel;
+ /* rgf */
+ /* GCperDepth */
+ /* PixmapPerDepth */
+ /* WindowPrivateLen */
+ /* WindowPrivateSizes */
+ /* totalWindowSize */
+ /* GCPrivateLen */
+ /* GCPrivateSizes */
+ /* totalGCSize */
+
+ /*
+ * Random screen procedures.
+ */
+
+ pScreen->CloseScreen = nxagentCloseScreen;
+ pScreen->QueryBestSize = nxagentQueryBestSize;
+ pScreen->SaveScreen = nxagentSaveScreen;
+ pScreen->GetImage = nxagentGetImage;
+ pScreen->GetSpans = nxagentGetSpans;
+ pScreen->PointerNonInterestBox = (void (*)()) 0;
+ pScreen->SourceValidate = (void (*)()) 0;
+
+ pScreen->CreateScreenResources = nxagentCreateScreenResources;
+
+ /*
+ * Window Procedures.
+ *
+ * Note that the following functions are not
+ * replaced with nxagent counterparts:
+ *
+ * ValidateTreeProcPtr ValidateTree;
+ * ClearToBackgroundProcPtr ClearToBackground;
+ *
+ * Note also that the ConfigureWindow procedure
+ * has not a pointer in the screen structure.
+ */
+
+ pScreen->CreateWindow = nxagentCreateWindow;
+ pScreen->DestroyWindow = nxagentDestroyWindow;
+ pScreen->PositionWindow = nxagentPositionWindow;
+ pScreen->ChangeWindowAttributes = nxagentChangeWindowAttributes;
+ pScreen->RealizeWindow = nxagentRealizeWindow;
+ pScreen->UnrealizeWindow = nxagentUnrealizeWindow;
+ pScreen->PostValidateTree = nxagentPostValidateTree;
+ pScreen->WindowExposures = nxagentWindowExposures;
+ pScreen->PaintWindowBackground = nxagentPaintWindowBackground;
+ pScreen->PaintWindowBorder = nxagentPaintWindowBorder;
+ pScreen->CopyWindow = nxagentCopyWindow;
+ pScreen->ClipNotify = nxagentClipNotify;
+ pScreen->RestackWindow = nxagentRestackWindow;
+ pScreen->ReparentWindow = nxagentReparentWindow;
+
+ /*
+ * Pixmap procedures.
+ */
+
+ pScreen->CreatePixmap = nxagentCreatePixmap;
+ pScreen->DestroyPixmap = nxagentDestroyPixmap;
+
+ /*
+ * This is originally miModifyPixmapHeader()
+ * from miscrinit.c. It is used to recycle
+ * the scratch pixmap for this screen.
+ */
+
+ pScreen->ModifyPixmapHeader = nxagentModifyPixmapHeader;
+
+ /*
+ * Font procedures.
+ */
+
+ pScreen->RealizeFont = nxagentRealizeFont;
+ pScreen->UnrealizeFont = nxagentUnrealizeFont;
+
+ /*
+ * GC procedures.
+ */
+
+ pScreen->CreateGC = nxagentCreateGC;
+ pScreen->BitmapToRegion = nxagentPixmapToRegion;
+
+ /*
+ * Colormap procedures.
+ */
+
+ pScreen->CreateColormap = nxagentCreateColormap;
+ pScreen->DestroyColormap = nxagentDestroyColormap;
+ pScreen->InstallColormap = nxagentInstallColormap;
+ pScreen->UninstallColormap = nxagentUninstallColormap;
+ pScreen->ListInstalledColormaps = nxagentListInstalledColormaps;
+ pScreen->StoreColors = nxagentStoreColors;
+ pScreen->ResolveColor = nxagentResolveColor;
+
+ /*
+ * Backing store procedures.
+ */
+
+ pScreen->SaveDoomedAreas = (void (*)()) 0;
+ pScreen->RestoreAreas = (RegionPtr (*)()) 0;
+ pScreen->ExposeCopy = (void (*)()) 0;
+ pScreen->TranslateBackingStore = (RegionPtr (*)()) 0;
+ pScreen->ClearBackingStore = (RegionPtr (*)()) 0;
+ pScreen->DrawGuarantee = (void (*)()) 0;
+
+ if (enableBackingStore == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Going to initialize backing store.\n");
+ #endif
+
+ pScreen -> BackingStoreFuncs.SaveAreas = nxagentSaveAreas;
+ pScreen -> BackingStoreFuncs.RestoreAreas = nxagentRestoreAreas;
+ pScreen -> BackingStoreFuncs.SetClipmaskRgn = 0;
+ pScreen -> BackingStoreFuncs.GetImagePixmap = 0;
+ pScreen -> BackingStoreFuncs.GetSpansPixmap = 0;
+
+ miInitializeBackingStore(pScreen);
+ }
+
+ /*
+ * OS layer procedures.
+ */
+
+ pScreen->BlockHandler = (ScreenBlockHandlerProcPtr) NoopDDA;
+ pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr) NoopDDA;
+ pScreen->blockData = NULL;
+ pScreen->wakeupData = NULL;
+
+ #ifdef RENDER
+
+ /*
+ * Initialize picture support. This have to be
+ * placed here because miDCInitialize calls
+ * DamageSetup, that should wrap the picture
+ * screen functions. So PictureInit has to be
+ * called before.
+ */
+
+ if (nxagentRenderEnable && !nxagentReconnectTrap)
+ {
+ if (!nxagentPictureInit(pScreen, 0, 0))
+ {
+ nxagentRenderEnable = False;
+
+ return FALSE;
+ }
+
+ if (nxagentAlphaEnabled)
+ {
+ fprintf(stderr, "Info: Using alpha channel in render extension.\n");
+ }
+ }
+
+ #endif /* RENDER */
+
+ /*
+ * From misprite.c: called from device-dependent screen
+ * initialization proc after all of the function pointers
+ * have been stored in the screen structure.
+ */
+
+ miDCInitialize(pScreen, &nxagentPointerCursorFuncs);
+
+ /*
+ * Cursor Procedures.
+ */
+
+ pScreen->ConstrainCursor = nxagentConstrainCursor;
+ pScreen->CursorLimits = nxagentCursorLimits;
+ pScreen->DisplayCursor = nxagentDisplayCursor;
+ pScreen->RealizeCursor = nxagentRealizeCursor;
+ pScreen->UnrealizeCursor = nxagentUnrealizeCursor;
+ pScreen->RecolorCursor = nxagentRecolorCursor;
+
+ nxagentSetCursorPositionW = pScreen->SetCursorPosition;
+
+ pScreen->SetCursorPosition = nxagentSetCursorPosition;
+
+ #define POSITION_OFFSET (pScreen->myNum * (nxagentOption(Width) + \
+ nxagentOption(Height)) / 32)
+ }
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry(NULL, "nxagentOpenScreen:");
+ #endif
+
+ if (nxagentDoFullGeneration == 1 ||
+ nxagentReconnectTrap == 1)
+ {
+ valuemask = CWBackPixel | CWEventMask | CWColormap |
+ (nxagentOption(AllScreens) == 1 ? CWOverrideRedirect : 0);
+
+ attributes.background_pixel = nxagentBlackPixel;
+
+ /* Assume that the mask fits in int... broken on Big Endian 64bit systems. */
+ Mask tmp_mask = attributes.event_mask;
+ nxagentGetDefaultEventMask(&tmp_mask);
+ attributes.event_mask = (int)tmp_mask;
+
+ attributes.colormap = nxagentDefaultVisualColormap(nxagentDefaultVisual(pScreen));
+
+ if (nxagentOption(AllScreens) == 1)
+ {
+ attributes.override_redirect = True;
+ }
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ if (nxagentReconnectTrap)
+ {
+ /*
+ * We need to disable the host's screensaver or
+ * it will otherwise grab the screen even if it
+ * is under agent's control.
+ */
+
+ XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
+ }
+ }
+
+ /*
+ * This would be used when running agent
+ * embedded into another X window.
+ */
+
+ if (nxagentParentWindow != 0)
+ {
+ nxagentDefaultWindows[pScreen->myNum] = nxagentParentWindow;
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], mask);
+ }
+ else
+ {
+ /*
+ * Create any top-level window as a child of the
+ * real root of the remote display. See also the
+ * InitRootWindow() procedure and the function
+ * handling the splash screen.
+ */
+
+ if (nxagentOption(Rootless) == True)
+ {
+ nxagentDefaultWindows[pScreen->myNum] = DefaultRootWindow(nxagentDisplay);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Using root window id [%ld].\n",
+ (long int)nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Going to create new default window.\n");
+ #endif
+
+ nxagentDefaultWindows[pScreen->myNum] =
+ XCreateWindow(nxagentDisplay,
+ DefaultRootWindow(nxagentDisplay),
+ nxagentOption(X) + POSITION_OFFSET,
+ nxagentOption(Y) + POSITION_OFFSET,
+ nxagentOption(Width),
+ nxagentOption(Height),
+ nxagentOption(BorderWidth),
+ pScreen->rootDepth,
+ InputOutput,
+ nxagentDefaultVisual(pScreen),
+ valuemask, &attributes);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ valuemask = CWEventMask;
+ mask = PointerMotionMask;
+ attributes.event_mask = mask;
+
+ nxagentInputWindows[pScreen -> myNum] =
+ XCreateWindow(nxagentDisplay,
+ nxagentDefaultWindows[pScreen -> myNum],
+ 0, 0,
+ nxagentOption(Width),
+ nxagentOption(Height),
+ 0, 0, InputOnly,
+ nxagentDefaultVisual(pScreen),
+ valuemask , &attributes);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Created new default window with id [%ld].\n",
+ (long int)nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+
+ /*
+ * Setting WM_CLASS to "X2GoAgent" when running in X2Go Agent mode
+ * we need it to properly display all window parameters by some WMs
+ * (for example on Maemo)
+ */
+ if(nxagentX2go)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Setting WM_CLASS and WM_NAME for window withid [%ld].\n",
+ (long int)nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+ XClassHint hint;
+ hint.res_name=malloc(strlen("X2GoAgent")+1);
+ hint.res_class=malloc(strlen("X2GoAgent")+1);
+ strcpy(hint.res_name,"X2GoAgent");
+ strcpy(hint.res_class,"X2GoAgent");
+ XSetClassHint(nxagentDisplay,nxagentDefaultWindows[pScreen->myNum],&hint);
+ free(hint.res_name);
+ free(hint.res_class);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Setting WM_CLASS and WM_NAME for window withid [%ld].\n",
+ (long int)nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+
+ XClassHint hint;
+ hint.res_name=malloc(strlen("NXAgent")+1);
+ hint.res_class=malloc(strlen("NXAgent")+1);
+ strcpy(hint.res_name,"NXAgent");
+ strcpy(hint.res_class,"NXAgent");
+ XSetClassHint(nxagentDisplay,nxagentDefaultWindows[pScreen->myNum],&hint);
+ free(hint.res_name);
+ free(hint.res_class);
+ }
+
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentFullscreenWindow = nxagentDefaultWindows[pScreen->myNum];
+ }
+
+ if (nxagentIpaq)
+ {
+ XWindowChanges ch;
+ unsigned int ch_mask;
+
+ ch.stack_mode = Below;
+ ch_mask = CWStackMode;
+
+ XConfigureWindow(nxagentDisplay, nxagentFullscreenWindow, ch_mask, &ch);
+ }
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ /*
+ * FIXME: Do we still need to set this property?
+ */
+
+ if (nxagentAtoms[8] != 0)
+ {
+ XChangeProperty(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentAtoms[8], /* NX_AGENT_SIGNATURE */
+ XA_STRING,
+ 8,
+ PropModeReplace,
+ (unsigned char*) "X-AGENT",
+ strlen("X-AGENT"));
+ }
+
+ nxagentGetDefaultEventMask(&mask);
+
+ XSelectInput(nxagentDisplay, nxagentFullscreenWindow, mask);
+ }
+
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X) + POSITION_OFFSET;
+ sizeHints.y = nxagentOption(Y) + POSITION_OFFSET;
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+
+ sizeHints.width = nxagentOption(RootWidth);
+ sizeHints.height = nxagentOption(RootHeight);
+
+ if (nxagentOption(DesktopResize) == 1 || nxagentOption(Fullscreen) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ sizeHints.flags |= USPosition;
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ sizeHints.flags |= USSize;
+
+ XSetStandardProperties(nxagentDisplay,
+ nxagentDefaultWindows[pScreen->myNum],
+ nxagentWindowName,
+ nxagentWindowName,
+ nxagentIconPixmap,
+ argv, argc, &sizeHints);
+
+ wmHints.icon_pixmap = nxagentIconPixmap;
+
+ if (useXpmIcon)
+ {
+ wmHints.icon_mask = nxagentIconShape;
+ wmHints.flags = IconPixmapHint | IconMaskHint;
+ }
+ else
+ {
+ wmHints.flags = IconPixmapHint;
+ }
+
+ XSetWMHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &wmHints);
+
+ /*
+ * Clear the window but let it unmapped. We'll map it
+ * at the time the we'll initialize our screen root
+ * and only if we are not running in rootless mode.
+ */
+
+ XClearWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]);
+
+ if (nxagentOption(AllScreens))
+ {
+ if (nxagentReconnectTrap)
+ {
+ XGrabKeyboard(nxagentDisplay, nxagentFullscreenWindow, True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+
+ nxagentIconWindow = nxagentCreateIconWindow();
+ }
+ else
+ {
+ nxagentIconWindow = 0;
+ }
+
+ /*
+ * When we don't have window manager we grab keyboard
+ * to let nxagent get keyboard events.
+ */
+
+ if (!nxagentWMIsRunning && !nxagentOption(Fullscreen))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: No window manager, we call XGrabKeyboard.\n");
+ #endif
+
+ XGrabKeyboard(nxagentDisplay, RootWindow (nxagentDisplay, 0), True, GrabModeAsync,
+ GrabModeAsync, CurrentTime);
+ }
+ }
+
+ if (!nxagentCreateDefaultColormap(pScreen))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentOpenScreen: Failed to create default colormap for screen.\n");
+ #endif
+
+ return False;
+ }
+
+ /*
+ * The purpose of this check is to verify if there
+ * is a window manager running. Unfortunately due
+ * to the way we manage the intern atoms call, the
+ * atom will always exist.
+ */
+
+ if (nxagentWMIsRunning)
+ {
+ XlibAtom deleteWMatom = nxagentAtoms[2]; /* WM_DELETE_WINDOW */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: Found WM, delete window atom [%ld].\n",
+ deleteWMatom);
+ #endif
+
+ if (nxagentOption(Rootless) == False)
+ {
+ /*
+ * Set the WM_DELETE_WINDOW protocol for the main agent
+ * window and, if we are in fullscreen mode, include the
+ * icon window.
+ */
+
+ XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1);
+ }
+ else
+ {
+ /*
+ * We need to register the ICCCM WM_DELETE_WINDOW
+ * protocol for any top-level window or the agent
+ * will be killed if any window is closed.
+ */
+
+ XSetWMProtocols(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &deleteWMatom, 1);
+
+ #ifdef TEST
+ fprintf(stderr, "Warning: Not setting the WM_DELETE_WINDOW protocol.\n");
+ #endif
+ }
+ }
+ else
+ {
+ /*
+ * We should always enable the configuration of the
+ * remote X server's devices if we are running full-
+ * screen and there is no WM running.
+ */
+
+ if (nxagentOption(Fullscreen))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentOpenScreen: WARNING! Forcing propagation of device control changes.\n");
+ #endif
+
+ nxagentChangeOption(DeviceControl, True);
+ }
+ }
+
+ /*
+ * Inform the user whether the agent's clients will
+ * be able to change the real X server's keyboard
+ * and pointer settings.
+ */
+
+ if (nxagentOption(DeviceControl) == False)
+ {
+ fprintf(stderr, "Info: Not using local device configuration changes.\n");
+ }
+ else
+ {
+ fprintf(stderr, "Info: Using local device configuration changes.\n");
+ }
+
+ #ifdef RENDER
+
+ /*
+ * if (nxagentRenderEnable && !nxagentReconnectTrap)
+ * {
+ * if (!nxagentPictureInit(pScreen, 0, 0))
+ * {
+ * nxagentRenderEnable = False;
+ *
+ * return FALSE;
+ * }
+ *
+ * if (nxagentAlphaEnabled)
+ * {
+ * fprintf(stderr, "Info: Using alpha channel in render extension.\n");
+ * }
+ * }
+ */
+
+ #endif /* RENDER */
+
+ /*
+ * Check if the composite extension is
+ * supported on the remote display and
+ * prepare the agent for its use.
+ */
+
+ nxagentCompositeExtensionInit();
+
+ /* We use this to get informed about RandR changes on the real display.
+ FIXME: It would probably be better to use an RRScreenChangeNotifyEvent here. */
+ XSelectInput(nxagentDisplay, DefaultRootWindow(nxagentDisplay), StructureNotifyMask);
+
+ #ifdef NXAGENT_TIMESTAMP
+
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "Screen: open screen finished, time is [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+
+ #endif
+
+ #ifdef WATCH
+
+ fprintf(stderr, "nxagentOpenScreen: Watchpoint 8.\n");
+
+/*
+Reply Total Cached Bits In Bits Out Bits/Reply Ratio
+------- ----- ------ ------- -------- ---------- -----
+#1 U 2 1 5344 bits (1 KB) -> 2344 bits (0 KB) -> 2672/1 -> 1172/1 = 2.280:1
+#16 11 2816 bits (0 KB) -> 197 bits (0 KB) -> 256/1 -> 18/1 = 14.294:1
+#91 1 16640 bits (2 KB) -> 12314 bits (2 KB) -> 16640/1 -> 12314/1 = 1.351:1
+#98 2 512 bits (0 KB) -> 57 bits (0 KB) -> 256/1 -> 28/1 = 8.982:1
+*/
+
+ sleep(30);
+
+ #endif
+
+ return True;
+}
+
+Bool nxagentCloseScreen(ScreenPtr pScreen)
+{
+ int i;
+
+ #ifdef DEBUG
+ fprintf(stderr, "running nxagentCloseScreen()\n");
+ #endif
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ free(pScreen->allowedDepths[i].vids);
+ }
+
+ /*
+ * Free the frame buffer.
+ */
+
+ free(((PixmapPtr)pScreen -> devPrivate) -> devPrivate.ptr);
+
+ free(pScreen->allowedDepths);
+ free(pScreen->visuals);
+ free(pScreen->devPrivate);
+
+ /*
+ * Reset the geometry and alpha information
+ * used by proxy to unpack the packed images.
+ */
+
+ nxagentResetVisualCache();
+ nxagentResetAlphaCache();
+ nxagentReleaseAllSplits();
+
+ /*
+ * The assumption is that all X resources will be
+ * destroyed upon closing the display connection.
+ * There is no need to generate extra protocol.
+ */
+
+ return True;
+}
+
+/*
+ * This function comes from the xfree86 Xserver.
+ */
+
+static void nxagentSetRootClip (ScreenPtr pScreen, Bool enable)
+{
+ WindowPtr pWin = pScreen->root;
+ WindowPtr pChild;
+ Bool WasViewable = (Bool)(pWin->viewable);
+ Bool anyMarked = FALSE;
+ RegionPtr pOldClip = NULL, bsExposed;
+#ifdef DO_SAVE_UNDERS
+ Bool dosave = FALSE;
+#endif
+ WindowPtr pLayerWin;
+ BoxRec box;
+
+ if (WasViewable)
+ {
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
+ {
+ (void) (*pScreen->MarkOverlappedWindows)(pChild,
+ pChild,
+ &pLayerWin);
+ }
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ if (pWin->valdata)
+ {
+ if (HasBorder (pWin))
+ {
+ RegionPtr borderVisible;
+
+ borderVisible = RegionCreate(NullBox, 1);
+ RegionSubtract(borderVisible,
+ &pWin->borderClip, &pWin->winSize);
+ pWin->valdata->before.borderVisible = borderVisible;
+ }
+ pWin->valdata->before.resized = TRUE;
+ }
+ }
+
+ /*
+ * Use REGION_BREAK to avoid optimizations in ValidateTree
+ * that assume the root borderClip can't change well, normally
+ * it doesn't...)
+ */
+ if (enable)
+ {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ RegionInit(&pWin->winSize, &box, 1);
+ RegionInit(&pWin->borderSize, &box, 1);
+ if (WasViewable)
+ RegionReset(&pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ RegionBreak(&pWin->clipList);
+ }
+ else
+ {
+ RegionEmpty(&pWin->borderClip);
+ RegionBreak(&pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = RegionCreate(NullBox, 1);
+ RegionCopy(pOldClip, &pWin->clipList);
+ }
+
+ if (pWin->firstChild)
+ {
+ anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
+ pWin->firstChild,
+ (WindowPtr *)NULL);
+ }
+ else
+ {
+ (*pScreen->MarkWindow) (pWin);
+ anyMarked = TRUE;
+ }
+
+#ifdef DO_SAVE_UNDERS
+ if (DO_SAVE_UNDERS(pWin))
+ {
+ dosave = (*pScreen->ChangeSaveUnder)(pLayerWin, pLayerWin);
+ }
+#endif /* DO_SAVE_UNDERS */
+
+ if (anyMarked)
+ (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
+ }
+
+ if (pWin->backStorage && pOldClip &&
+ ((pWin->backingStore == Always) || WasViewable))
+ {
+ if (!WasViewable)
+ pOldClip = &pWin->clipList; /* a convenient empty region */
+ bsExposed = (*pScreen->TranslateBackingStore)
+ (pWin, 0, 0, pOldClip,
+ pWin->drawable.x, pWin->drawable.y);
+ if (WasViewable)
+ RegionDestroy(pOldClip);
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
+
+ if (pWin->valdata)
+ valExposed = &pWin->valdata->after.exposed;
+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
+ if (valExposed)
+ RegionEmpty(valExposed);
+ RegionDestroy(bsExposed);
+ }
+ }
+ if (WasViewable)
+ {
+ if (anyMarked)
+ (*pScreen->HandleExposures)(pWin);
+#ifdef DO_SAVE_UNDERS
+ if (dosave)
+ (*pScreen->PostChangeSaveUnder)(pLayerWin, pLayerWin);
+#endif /* DO_SAVE_UNDERS */
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
+ }
+ if (pWin->realized)
+ WindowsRestructured ();
+ FlushAllOutput ();
+}
+
+Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height,
+ int mmWidth, int mmHeight)
+{
+ BoxRec box;
+ XSizeHints sizeHints;
+ PixmapPtr pPixmap;
+ char *fbBits;
+
+ int oldWidth;
+ int oldHeight;
+ int oldMmWidth;
+ int oldMmHeight;
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry("Before Resize Screen", "nxagentResizeScreen:");
+ #endif
+
+ /*
+ * Change screen properties.
+ */
+
+ oldWidth = pScreen -> width;
+ oldHeight = pScreen -> height;
+ oldMmWidth = pScreen -> mmWidth;
+ oldMmHeight = pScreen -> mmHeight;
+
+ pScreen -> width = width;
+ pScreen -> height = height;
+
+ /*
+ * Compute screen dimensions if they aren't given.
+ */
+
+ if (mmWidth == 0)
+ {
+ mmWidth = (width * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmWidth < 1)
+ {
+ mmWidth = 1;
+ }
+ }
+
+ if (mmHeight == 0)
+ {
+ mmHeight = (height * 254 + monitorResolution * 5) / (monitorResolution * 10);
+
+ if (mmHeight < 1)
+ {
+ mmHeight = 1;
+ }
+ }
+
+ pScreen -> mmWidth = mmWidth;
+ pScreen -> mmHeight = mmHeight;
+
+ pPixmap = fbGetScreenPixmap(pScreen);
+
+ if ((fbBits = realloc(pPixmap -> devPrivate.ptr, PixmapBytePad(width, pScreen->rootDepth) *
+ height * BitsPerPixel(pScreen->rootDepth) / 8)) == NULL)
+ {
+ pScreen -> width = oldWidth;
+ pScreen -> height = oldHeight;
+ pScreen -> mmWidth = oldMmWidth;
+ pScreen -> mmHeight = oldMmHeight;
+
+ goto nxagentResizeScreenError;
+ }
+
+ if (!miModifyPixmapHeader(pPixmap, width, height,
+ pScreen->rootDepth, BitsPerPixel(pScreen->rootDepth),
+ PixmapBytePad(width,
+ pScreen->rootDepth), fbBits))
+ {
+/*
+FIXME: We should try to restore the previously
+ reallocated frame buffer pixmap.
+*/
+
+ pScreen -> width = oldWidth;
+ pScreen -> height = oldHeight;
+ pScreen -> mmWidth = oldMmWidth;
+ pScreen -> mmHeight = oldMmHeight;
+
+ goto nxagentResizeScreenError;
+ }
+
+ nxagentChangeOption(RootWidth, width);
+ nxagentChangeOption(RootHeight, height);
+
+ if (nxagentOption(Fullscreen))
+ {
+ nxagentChangeOption(RootX, (nxagentOption(Width) -
+ nxagentOption(RootWidth)) / 2);
+ nxagentChangeOption(RootY, (nxagentOption(Height) -
+ nxagentOption(RootHeight)) / 2);
+ }
+ else
+ {
+ nxagentChangeOption(RootX, 0);
+ nxagentChangeOption(RootY, 0);
+ }
+
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ /*
+ * Change agent window size and size hints.
+ */
+
+ if ((nxagentOption(Fullscreen) == 0 && nxagentOption(AllScreens) == 0))
+ {
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X);
+ sizeHints.y = nxagentOption(Y);
+
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+ sizeHints.width = width;
+ sizeHints.height = height;
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ {
+ sizeHints.flags |= USPosition;
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ {
+ sizeHints.flags |= USSize;
+ }
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints);
+
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], width, height);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ XResizeWindow(nxagentDisplay, nxagentInputWindows[pScreen -> myNum], width, height);
+ }
+ }
+
+ /*
+ * Set properties for the agent root window.
+ */
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = width;
+ box.y2 = height;
+
+ pScreen->root -> drawable.width = width;
+ pScreen->root -> drawable.height = height;
+ pScreen->root -> drawable.x = 0;
+ pScreen->root -> drawable.y = 0;
+
+ RegionInit(&pScreen->root -> borderSize, &box, 1);
+ RegionInit(&pScreen->root -> winSize, &box, 1);
+ RegionInit(&pScreen->root -> clipList, &box, 1);
+ RegionInit(&pScreen->root -> borderClip, &box, 1);
+
+ (*pScreen -> PositionWindow)(pScreen->root, 0, 0);
+
+ nxagentSetRootClip(pScreen, 1);
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(screenInfo.screens[0]->root),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ /*
+ * Update void * bounds.
+ */
+
+ ScreenRestructured(pScreen);
+
+ #ifdef TEST
+ nxagentPrintAgentGeometry("After Resize Screen", "nxagentResizeScreen:");
+ #endif
+
+ nxagentSetPrintGeometry(pScreen -> myNum);
+
+ return 1;
+
+nxagentResizeScreenError:
+
+ return 0;
+}
+
+void nxagentShadowSetRatio(float floatXRatio, float floatYRatio)
+{
+ int intXRatio;
+ int intYRatio;
+
+ if (floatXRatio == 0)
+ {
+ floatXRatio = 1.0;
+ }
+
+ if (floatYRatio == 0)
+ {
+ floatYRatio = 1.0;
+ }
+
+ intXRatio = floatXRatio * (1 << PRECISION);
+ intYRatio = floatYRatio * (1 << PRECISION);
+
+ nxagentChangeOption(FloatXRatio, floatXRatio);
+ nxagentChangeOption(FloatYRatio, floatYRatio);
+
+ nxagentChangeOption(XRatio, intXRatio);
+ nxagentChangeOption(YRatio, intYRatio);
+
+ #ifdef TEST
+ fprintf(stderr, "Info: Using X ratio [%f] Y ratio [%f].\n",
+ nxagentOption(FloatXRatio), nxagentOption(FloatYRatio));
+ #endif
+}
+
+void nxagentShadowSetWindowsSize(void)
+{
+ XResizeWindow(nxagentDisplay, nxagentDefaultWindows[0],
+ nxagentOption(Width), nxagentOption(Height));
+
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
+ nxagentOption(Width), nxagentOption(Height));
+}
+
+void nxagentShadowSetWindowOptions(void)
+{
+ nxagentChangeOption(RootWidth, nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)));
+ nxagentChangeOption(RootHeight, nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)));
+
+ nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
+
+ nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) >> 1);
+ nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) >> 1);
+}
+
+int nxagentShadowInit(ScreenPtr pScreen, WindowPtr pWin)
+{
+ int i;
+ char *layout = NULL;
+ extern char *nxagentKeyboard;
+ XlibGC gc;
+ XGCValues value;
+
+ #ifndef __CYGWIN32__
+
+ Atom nxagentShadowAtom;
+
+ int fd;
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "Info: Init shadow session. nxagentDisplayName [%s] "
+ "nxagentDisplay [%p] nxagentShadowDisplayName [%s].\n",
+ nxagentDisplayName, (void *) nxagentDisplay,
+ nxagentShadowDisplayName);
+ #endif
+
+ if (nxagentKeyboard != NULL)
+ {
+ for (i = 0; nxagentKeyboard[i] != '/' && nxagentKeyboard[i] != 0; i++);
+
+ if(nxagentKeyboard[i] == 0 || nxagentKeyboard[i + 1] == 0 || i == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr,"WARNING! Wrong keyboard type: %s.\n", nxagentKeyboard);
+ #endif
+ }
+ else
+ {
+ layout = malloc(strlen(&nxagentKeyboard[i + 1]) + 1);
+
+ strcpy(layout, &nxagentKeyboard[i + 1]);
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShadowInit: Setting the master uid [%d].\n",
+ nxagentShadowUid);
+ #endif
+
+#if !defined (__CYGWIN32__) && !defined (WIN32)
+
+ if (nxagentShadowUid != -1)
+ {
+ NXShadowSetDisplayUid(nxagentShadowUid);
+ }
+
+ if (nxagentOption(UseDamage) == 0)
+ {
+ NXShadowDisableDamage();
+ }
+
+#endif
+
+ if (NXShadowCreate(nxagentDisplay, layout, nxagentShadowDisplayName,
+ (void *) &nxagentShadowDisplay) != 1)
+ {
+ #ifdef PANIIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Failed to initialize shadow "
+ "display [%s].\n", nxagentShadowDisplayName);
+ #endif
+
+ return -1;
+ }
+
+ /*
+ * The shadow nxagent sets the _NX_SHADOW
+ * property on the master X server root
+ * window in order to notify its presence.
+ */
+
+ #ifndef __CYGWIN__
+
+ nxagentShadowAtom = XInternAtom(nxagentShadowDisplay, "_NX_SHADOW", False);
+
+ XChangeProperty(nxagentShadowDisplay, DefaultRootWindow(nxagentShadowDisplay),
+ nxagentShadowAtom, XA_STRING, 8, PropModeReplace, NULL, 0);
+ #endif
+
+ if (NXShadowAddUpdaterDisplay(nxagentDisplay, &nxagentShadowWidth,
+ &nxagentShadowHeight, &nxagentMasterDepth) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Failed to add display [%s].\n",
+ nxagentDisplayName);
+ #endif
+
+ return -1;
+ }
+
+ #ifndef __CYGWIN32__
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ nxagentShadowSetRatio(WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowWidth,
+ HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) * 1.0 / nxagentShadowHeight);
+ }
+ else if (nxagentUserGeometry.flag != 0)
+ {
+ nxagentShadowSetRatio(nxagentOption(RootWidth) * 1.0 / nxagentShadowWidth,
+ nxagentOption(RootHeight) * 1.0 / nxagentShadowHeight);
+ }
+
+ if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentDisplay)) ->
+ class != TrueColor)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! The visual class of the remote "
+ "X server is not TrueColor.\n");
+ #endif
+
+ return -1;
+ }
+
+ if (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) ->
+ class != TrueColor)
+ {
+ #ifdef PANIC
+
+ const char *className;
+
+ switch (DefaultVisualOfScreen(DefaultScreenOfDisplay(nxagentShadowDisplay)) -> class)
+ {
+ case StaticGray:
+ {
+ className = "StaticGray";
+
+ break;
+ }
+ case StaticColor:
+ {
+ className = "StaticColor";
+
+ break;
+ }
+ case PseudoColor:
+ {
+ className = "PseudoColor";
+
+ break;
+ }
+ case DirectColor:
+ {
+ className = "DirectColor";
+
+ break;
+ }
+ case GrayScale:
+ {
+ className = "GrayScale";
+
+ break;
+ }
+ default:
+ {
+ className = "";
+
+ break;
+ }
+ }
+
+ fprintf(stderr, "nxagentShadowInit: PANIC! Cannot shadow the display. "
+ "%s visual class is not supported. Only TrueColor visuals "
+ "are supported.\n", className);
+
+ #endif /* #endif PANIC */
+
+ return -1;
+ }
+
+ #endif
+
+ nxagentShadowDepth = pScreen -> rootDepth;
+
+ switch (nxagentMasterDepth)
+ {
+ case 32:
+ case 24:
+ {
+ if (nxagentShadowDepth == 16)
+ {
+ nxagentCheckDepth = 1;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a %d bit "
+ "display with a 8 bit screen depth.\n", nxagentMasterDepth);
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 4;
+
+ break;
+ }
+ case 16:
+ {
+ if (nxagentShadowDepth > 16)
+ {
+ nxagentCheckDepth = 1;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 16 bit "
+ "display with a 8 bit screen depth.\n");
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 2;
+
+ break;
+ }
+ case 8:
+ {
+ if (nxagentShadowDepth != 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! Unable to shadow a 8 bit "
+ "display with a %d bit screen depth.\n", nxagentShadowDepth);
+ #endif
+
+ return -1;
+ }
+
+ nxagentBppMaster = 1;
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowInit: PANIC! The depth is not 32, 24, 16 or 8 bit.\n");
+ #endif
+
+ return -1;
+ }
+ }
+
+ if (nxagentShadowDepth >= 24)
+ {
+ nxagentBppShadow = 4;
+ }
+ else if (nxagentShadowDepth == 16)
+ {
+ nxagentBppShadow = 2;
+ }
+ else if (nxagentShadowDepth == 8)
+ {
+ nxagentBppShadow = 1;
+ }
+
+#if !defined(__CYGWIN__)
+
+ imageByteOrder = nxagentShadowDisplay -> byte_order;
+
+ fd = XConnectionNumber(nxagentShadowDisplay);
+
+ nxagentShadowXConnectionNumber = fd;
+
+#endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddXConnection: Adding the X connection [%d] "
+ "to the device set.\n", fd);
+ #endif
+
+ SetNotifyFd(nxagentShadowXConnectionNumber, nxagentNotifyConnection, X_NOTIFY_READ, NULL);
+
+ accessPixmapID = FakeClientID(serverClient -> index);
+
+ AddResource(accessPixmapID, RT_PIXMAP, (void *)nxagentShadowPixmapPtr);
+
+ accessWindowID = FakeClientID(serverClient -> index);
+
+ AddResource(accessWindowID, RT_WINDOW, (void *)nxagentShadowWindowPtr);
+
+ nxagentResizeScreen(pScreen, nxagentShadowWidth, nxagentShadowHeight, pScreen -> mmWidth, pScreen -> mmHeight);
+
+ nxagentShadowCreateMainWindow(pScreen, pWin, nxagentShadowWidth, nxagentShadowHeight);
+
+ if (nxagentRemoteMajor <= 3)
+ {
+ nxagentShadowSetWindowsSize();
+
+ nxagentSetWMNormalHints(0);
+ }
+
+ XMapWindow(nxagentDisplay, nxagentDefaultWindows[0]);
+
+ /*
+ * Clean up the main window.
+ */
+
+ value.foreground = 0x00000000;
+ value.background = 0x00000000;
+ value.plane_mask = 0xffffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ XFillRectangle(nxagentDisplay, nxagentPixmap(nxagentShadowPixmapPtr), gc, 0, 0,
+ nxagentShadowWidth, nxagentShadowHeight);
+
+ XFreeGC(nxagentDisplay, gc);
+
+ RegionInit(&nxagentShadowUpdateRegion, (BoxRec*)NULL, 1);
+
+ return 0;
+}
+
+int nxagentShadowCreateMainWindow(ScreenPtr pScreen, WindowPtr pWin, int width, int height)
+{
+ XWindowChanges changes;
+ Mask mask,maskb;
+ XID values[4], *vlist;
+ int error;
+ XID xid;
+
+ nxagentShadowWidth = width;
+ nxagentShadowHeight = height;
+
+ NXShadowUpdateBuffer((void *)&nxagentShadowBuffer);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Update frame buffer [%p].\n", nxagentShadowBuffer);
+ #endif
+
+ nxagentShadowSetWindowOptions();
+
+ if (nxagentShadowPixmapPtr != NULL)
+ {
+ nxagentDestroyPixmap(nxagentShadowPixmapPtr);
+ }
+
+ if (nxagentShadowWindowPtr != NULL)
+ {
+ DeleteWindow(nxagentShadowWindowPtr, accessWindowID);
+ }
+
+ nxagentShadowPixmapPtr = nxagentCreatePixmap(pScreen, nxagentShadowWidth, nxagentShadowHeight, nxagentShadowDepth, 0);
+
+ if (nxagentShadowPixmapPtr)
+ {
+ ChangeResourceValue(accessPixmapID, RT_PIXMAP, (void *) nxagentShadowPixmapPtr);
+ nxagentShadowPixmapPtr -> drawable.id = accessPixmapID;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: nxagentShadowPixmapPtr [%p] PixmapM -> drawable.id [%lu].\n",
+ (void *)nxagentShadowPixmapPtr, nxagentShadowPixmapPtr -> drawable.id);
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Create pixmap with width [%d] height [%d] depth [%d].\n",
+ nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth);
+ #endif
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create pixmap with width [%d] height [%d] depth [%d].\n",
+ nxagentShadowWidth, nxagentShadowHeight, (int)nxagentShadowDepth);
+ #endif
+ }
+
+ XFreePixmap(nxagentDisplay, nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr)));
+
+ xid = XCreatePixmap(nxagentDisplay, nxagentDefaultWindows[0],
+ nxagentScale(nxagentShadowWidth, nxagentOption(XRatio)),
+ nxagentScale(nxagentShadowHeight, nxagentOption(YRatio)), nxagentShadowDepth);
+
+ nxagentPixmap(nxagentVirtualPixmap(nxagentShadowPixmapPtr)) = xid;
+
+ nxagentPixmap(nxagentRealPixmap(nxagentShadowPixmapPtr)) = xid;
+
+ if (nxagentShadowGCPtr != NULL)
+ {
+ FreeScratchGC(nxagentShadowGCPtr);
+ }
+/*
+ * FIXME: Should use CreateGC.
+ */
+ nxagentShadowGCPtr = GetScratchGC(nxagentShadowPixmapPtr -> drawable.depth, nxagentShadowPixmapPtr -> drawable.pScreen);
+
+ if (nxagentShadowGCPtr)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Created GC with pGC[%p]\n", (void *) nxagentShadowGCPtr);
+ #endif
+ ValidateGC((DrawablePtr)nxagentShadowPixmapPtr, nxagentShadowGCPtr);
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create GC.");
+ #endif
+ }
+
+ mask = CWBackPixmap | CWEventMask | CWCursor;
+
+ nxagentGetDefaultEventMask(&maskb);
+ maskb |= ResizeRedirectMask | ExposureMask;
+
+ vlist = values;
+ *vlist++ = (XID)nxagentShadowPixmapPtr -> drawable.id;
+ *vlist++ = (XID)maskb;
+
+ *vlist = (XID)None;
+
+ nxagentShadowWindowPtr = CreateWindow(accessWindowID, pWin, 0, 0, nxagentShadowWidth,
+ nxagentShadowHeight, 0, InputOutput, mask, (XID *)values,
+ nxagentShadowDepth, serverClient, CopyFromParent, &error);
+
+ mask = CWWidth | CWHeight;
+ changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio));
+ changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio));
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr), mask, &changes);
+
+ nxagentMoveViewport(pScreen, 0, 0);
+
+ if (nxagentShadowWindowPtr && !error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Create window with nxagentShadowWindowPtr [%p]"
+ "nxagentShadowWindowPtr -> drawable.id [%lu].\n", (void *) nxagentShadowWindowPtr,
+ nxagentShadowWindowPtr -> drawable.id);
+
+ fprintf(stderr, "nxagentShadowCreateMainWindow: parent nxagentShadowWindowPtr [%p] parent -> drawable.id [%lu].\n",
+ (void *)nxagentShadowWindowPtr->parent, nxagentShadowWindowPtr -> parent -> drawable.id);
+
+ #endif
+
+ ChangeResourceValue(accessWindowID, RT_WINDOW, (void *) nxagentShadowWindowPtr);
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowCreateMainWindow: PANIC! Failed to create window.\n");
+ #endif
+ }
+
+ XMapWindow(nxagentDisplay, nxagentWindow(nxagentShadowWindowPtr));
+ MapWindow(nxagentShadowWindowPtr, serverClient);
+
+ mask = CWX | CWY | CWWidth | CWHeight;
+ changes.x = nxagentOption(RootX);
+ changes.y = nxagentOption(RootY);
+ changes.width = nxagentScale(nxagentShadowWidth, nxagentOption(XRatio));
+ changes.height = nxagentScale(nxagentShadowHeight, nxagentOption(YRatio));
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), mask, &changes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowCreateMainWindow: Completed mapping of Access window.\n");
+ #endif
+
+ return 0;
+}
+
+int nxagentShadowSendUpdates(int *suspended)
+{
+ *suspended = 0;
+
+ if (RegionNil(&nxagentShadowUpdateRegion) == 1)
+ {
+ return 0;
+ }
+
+ nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &nxagentShadowUpdateRegion);
+
+ RegionEmpty(&nxagentShadowUpdateRegion);
+
+ return 1;
+}
+
+int nxagentShadowPoll(PixmapPtr nxagentShadowPixmapPtr, GCPtr nxagentShadowGCPtr,
+ unsigned char nxagentShadowDepth, int nxagentShadowWidth,
+ int nxagentShadowHeight, char *nxagentShadowBuffer, int *changed, int *suspended)
+{
+ int x, y, y2, n, c, line;
+ int result;
+ long numRects;
+ unsigned int width, height, length;
+ char *tBuffer = NULL;
+ char *iBuffer, *ptBox;
+ BoxRec *pBox;
+ RegionRec updateRegion;
+ RegionRec tempRegion;
+ BoxRec box;
+ int overlap;
+
+
+ RegionNull(&updateRegion);
+
+ RegionNull(&tempRegion);
+
+#ifdef __CYGWIN32__
+
+ if (NXShadowCaptureCursor(nxagentWindow(nxagentShadowWindowPtr),
+ nxagentShadowWindowPtr -> drawable.pScreen -> visuals) == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShadowPoll: Failed to capture cursor.\n");
+ #endif
+ }
+
+#endif
+
+ result = NXShadowHasChanged(nxagentUserInput, NULL, suspended);
+
+ *changed = result;
+
+ if (result == 1)
+ {
+ if (nxagentWMPassed == 0)
+ {
+ nxagentRemoveSplashWindow(NULL);
+ }
+
+ NXShadowExportChanges(&numRects, &ptBox);
+ pBox = (BoxRec *)ptBox;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowPoll: nRects[%ld], pBox[%p] depth[%d].\n", numRects, (void *) pBox, nxagentShadowDepth);
+ #endif
+
+ for (n = 0; n < numRects; n++)
+ {
+ /*
+ * The BoxRec struct defined in the Xserver has a different
+ * variable order in comparison with the BoxRec struct in the Xlib.
+ * the second and third field are inverted.
+ */
+
+ x = pBox[n].x1;
+ y = pBox[n].x2;
+ y2 = pBox[n].y2;
+ width = pBox[n].y1 - pBox[n].x1;/* y1 = x2 */
+ height = y2 - pBox[n].x2; /* x2 = y1 */
+
+ if((x + width) > nxagentShadowWidth || (y + height) > nxagentShadowHeight)
+ {
+ /*
+ * Out of bounds. Maybe a resize of the master session is going on.
+ */
+
+ continue;
+ }
+
+ line = PixmapBytePad(width, nxagentMasterDepth);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShadowPoll: Rectangle Number[%d] - x[%d]y[%d]W[%u]H[%u].\n", n+1, x, y, width, height);
+ #endif
+
+ length = nxagentImageLength(width, height, ZPixmap, 0, nxagentMasterDepth);
+
+ if (tBuffer)
+ {
+ free(tBuffer);
+ }
+
+ tBuffer = malloc(length);
+
+ if (tBuffer == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentShadowPoll: malloc failed.\n");
+ #endif
+
+ return -1;
+ }
+
+ iBuffer = tBuffer;
+
+ for (c = 0; c + y < y2; c++)
+ {
+ memcpy(tBuffer, nxagentShadowBuffer + x * nxagentBppMaster +
+ (y + c) * nxagentShadowWidth * nxagentBppMaster, line);
+
+ tBuffer += line;
+
+ }
+
+ tBuffer = iBuffer;
+
+#ifdef __CYGWIN32__
+ if (nxagentBppMaster == 2)
+ {
+ NXShadowCorrectColor(length, tBuffer);
+ }
+#else
+ if (nxagentCheckDepth == 1)
+ {
+ nxagentShadowAdaptDepth(width, height, line, &tBuffer);
+ }
+#endif
+
+ fbPutImage(nxagentVirtualDrawable((DrawablePtr)nxagentShadowPixmapPtr), nxagentShadowGCPtr,
+ nxagentShadowDepth, x, y, width, height, 0, ZPixmap, tBuffer);
+
+ box.x1 = x;
+ box.x2 = x + width;
+ box.y1 = y;
+ box.y2 = y + height;
+
+ RegionInit(&tempRegion, &box, 1);
+
+ RegionAppend(&updateRegion, &tempRegion);
+
+ RegionUninit(&tempRegion);
+
+ RegionValidate(&updateRegion, &overlap);
+
+ RegionUnion(&nxagentShadowUpdateRegion, &nxagentShadowUpdateRegion, &updateRegion);
+ }
+
+ if (tBuffer)
+ {
+ free(tBuffer);
+ }
+
+ RegionUninit(&updateRegion);
+ }
+ else if (result == -1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentShadowPoll: polling failed!\n");
+ #endif
+
+ usleep(50 * 1000);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+void nxagentShadowAdaptDepth(unsigned int width, unsigned int height,
+ unsigned int lineMaster, char **buffer)
+{
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned short color16 = 0;
+ unsigned char * icBuffer;
+ unsigned char * cBuffer = NULL;
+ unsigned char * tBuffer = (unsigned char *) *buffer;
+ unsigned int lineShadow;
+ unsigned int length;
+ unsigned int c;
+ unsigned int pad;
+ unsigned int color32 = 0;
+ unsigned long redMask;
+ unsigned long greenMask;
+ unsigned long blueMask;
+ Visual *pVisual;
+
+ length = nxagentImageLength(width, height, ZPixmap, 0, nxagentShadowDepth);
+
+ cBuffer = malloc(length);
+ icBuffer = cBuffer;
+
+ pVisual = nxagentImageVisual((DrawablePtr) nxagentShadowPixmapPtr, nxagentShadowDepth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCorrectDepthShadow: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: Shadow redMask [%lu] greenMask[%lu] blueMask[%lu].\n",
+ pVisual -> red_mask, pVisual -> green_mask, pVisual -> blue_mask);
+ #endif
+
+ redMask = nxagentShadowDisplay -> screens[0].root_visual[0].red_mask;
+ greenMask = nxagentShadowDisplay -> screens[0].root_visual[0].green_mask;
+ blueMask = nxagentShadowDisplay -> screens[0].root_visual[0].blue_mask;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: Master redMask [%lu] greenMask[%lu] blueMask[%lu].\n",
+ redMask, greenMask, blueMask);
+ #endif
+
+ switch(nxagentMasterDepth)
+ {
+ /*
+ * The Shadow agent has 24 bit depth.
+ */
+ case 16:
+ {
+ pad = lineMaster - nxagentBppMaster * width;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineMaster, width, pad);
+ #endif
+
+ while (height > 0)
+ {
+ for (c = 0; c < width ; c++)
+ {
+ if (imageByteOrder == LSBFirst)
+ {
+ color16 = *tBuffer++;
+ color16 |= (*tBuffer << 8);
+ }
+ else
+ {
+ color16 = (*tBuffer++) << 8;
+ color16 |= *tBuffer;
+ }
+
+ blue = ((short) blueMask & color16) << 3;
+ blue |= 0x3;
+
+ if (greenMask == 0x7e0)
+ {
+ /*
+ * bit mask 5-6-5
+ */
+
+ green = ((short) greenMask & color16) >> 3;
+ green |= 0x2;
+
+ red = ((short) redMask & color16) >> 8;
+ red |= 0x3;
+ }
+ else
+ {
+ /*
+ * bit mask 5-5-5
+ */
+
+ green = ((short) greenMask & color16) >> 2;
+ green |= 0x3;
+
+ red = ((short) redMask & color16) >> 7;
+ red |= 0x3;
+ }
+
+ tBuffer++;
+
+ if (nxagentDisplay -> byte_order == LSBFirst)
+ {
+ *cBuffer++ = blue;
+ *cBuffer++ = green;
+ *cBuffer++ = red;
+ cBuffer++;
+ }
+ else
+ {
+ cBuffer++;
+ *cBuffer++ = red;
+ *cBuffer++ = green;
+ *cBuffer++ = blue;
+ }
+ }
+ tBuffer += pad;
+ height--;
+ }
+ break;
+ }
+
+ /*
+ * The Shadow agent has 16 bit depth.
+ */
+ case 24:
+ {
+ lineShadow = PixmapBytePad(width, nxagentShadowDepth);
+
+ pad = lineShadow - nxagentBppShadow * width;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCorrectDepthShadow: line [%d] width[%d] pad[%d].\n", lineShadow, width, pad);
+ #endif
+
+ while (height > 0)
+ {
+ for (c = 0; c < width; c++)
+ {
+ if (imageByteOrder == LSBFirst)
+ {
+ color32 = *tBuffer++;
+ color32 |= (*tBuffer++ << 8);
+ color32 |= (*tBuffer++ << 16);
+ tBuffer++;
+ }
+ else
+ {
+ tBuffer++;
+ color32 = (*tBuffer++ << 16);
+ color32 |= (*tBuffer++ << 8);
+ color32 |= *tBuffer++;
+ }
+
+ color16 = (color32 & (pVisual -> blue_mask << 3)) >> 3;
+
+ if (pVisual -> green_mask == 0x7e0)
+ {
+ /*
+ * bit mask 5-6-5
+ */
+ color16 |= (color32 & (pVisual -> green_mask << 5)) >> 5;
+ color16 |= (color32 & (pVisual -> red_mask << 8)) >> 8;
+ }
+ else
+ {
+ /*
+ * bit mask 5-5-5
+ */
+ color16 |= (color32 & (pVisual -> green_mask << 6)) >> 6;
+ color16 |= (color32 & (pVisual -> red_mask << 9)) >> 9;
+ }
+
+ if (nxagentDisplay -> byte_order == LSBFirst)
+ {
+ *cBuffer++ = color16 & 0xff;
+ *cBuffer++ = (color16 & 0xff00) >> 8;
+ }
+ else
+ {
+ *cBuffer++ = (color16 & 0xff00) >> 8;
+ *cBuffer++ = color16 & 0xff;
+ }
+ }
+ cBuffer += pad;
+ height--;
+ }
+ break;
+ }
+ }
+ cBuffer = (unsigned char *) *buffer;
+ *buffer = (char *) icBuffer;
+
+ if (cBuffer != NULL)
+ {
+ free(cBuffer);
+ }
+}
+
+#ifdef NXAGENT_ARTSD
+
+unsigned char fromHexNibble(char c)
+{
+ int uc = (unsigned char)c;
+
+ if(uc >= '0' && uc <= '9') return uc - (unsigned char)'0';
+ if(uc >= 'a' && uc <= 'f') return uc + 10 - (unsigned char)'a';
+ if(uc >= 'A' && uc <= 'F') return uc + 10 - (unsigned char)'A';
+
+ return 16; /*error*/
+}
+
+void nxagentPropagateArtsdProperties(ScreenPtr pScreen, char *port)
+{
+ Window rootWin;
+ XlibAtom atomReturnType;
+ XlibAtom propAtom;
+ int iReturnFormat;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ unsigned char *pszReturnData = NULL;
+ int iReturn;
+
+ int i,in;
+ char tchar[] = " ";
+/*
+FIXME: The port information is not used at the moment and produces a
+ warning on recent gcc versions. Do we need such information
+ to run the audio forawrding?
+
+ char *chport;
+ char hex[] = "0123456789abcdef";
+*/
+ rootWin = DefaultRootWindow(nxagentDisplay);
+ propAtom = nxagentAtoms[4]; /* MCOPGLOBALS */
+
+ /*
+ * Get at most 64KB of data.
+ */
+
+ iReturn = XGetWindowProperty(nxagentDisplay,
+ rootWin,
+ propAtom,
+ 0,
+ 65536 / 4,
+ False,
+ XA_STRING,
+ &atomReturnType,
+ &iReturnFormat,
+ &ulReturnItems,
+ &ulReturnBytesLeft,
+ &pszReturnData);
+
+ if (iReturn == Success && atomReturnType != None &&
+ ulReturnItems > 0 && pszReturnData != NULL)
+ {
+ char *local_buf;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPropagateArtsdProperties: Got [%ld] elements of format [%d] with [%ld] bytes left.\n",
+ ulReturnItems, iReturnFormat, ulReturnBytesLeft);
+ #endif
+
+ #ifdef WARNING
+
+ if (ulReturnBytesLeft > 0)
+ {
+ fprintf(stderr, "nxagentPropagateArtsdProperties: WARNING! Could not get the whole ARTSD property data.\n");
+ }
+
+ #endif
+
+ local_buf = (char *) malloc(strlen((char*)pszReturnData) + 100);
+
+ if (local_buf)
+ {
+ memset(local_buf, 0, strlen((char *) pszReturnData));
+
+ for (i = 0, in = 0; pszReturnData[i] != '\0'; i++)
+ {
+ local_buf[in]=pszReturnData[i];
+
+ if(pszReturnData[i]==':')
+ {
+ i++;
+
+ while(pszReturnData[i]!='\n')
+ {
+ unsigned char h;
+ unsigned char l;
+
+ h = fromHexNibble(pszReturnData[i]);
+ i++;
+ if(pszReturnData[i]=='\0') continue;
+ l = fromHexNibble(pszReturnData[i]);
+ i++;
+
+ if(h >= 16 || l >= 16) continue;
+
+ /*
+ * FIXME: The array tchar[] was used uninitialized.
+ * It's not clear to me the original purpose of the
+ * piece of code using it. To be removed in future
+ * versions.
+ */
+
+ tchar[0]=tchar[1];
+ tchar[1]=tchar[2];
+ tchar[2]=tchar[3];
+ tchar[3] = (h << 4) + l;
+ tchar[4]='\0';
+
+ if (strncmp(tchar, "tcp:", 4) == 0)
+ {
+ local_buf[in-7]='1';
+ local_buf[in-6]=strlen(port)+47;
+
+ in++;
+ local_buf[in]=pszReturnData[i-2];
+ in++;
+ local_buf[in]=pszReturnData[i-1];
+
+ strcat(local_buf,"6c6f63616c686f73743a");
+ in+=20;
+
+/*
+FIXME: The port information is not used at the moment and produces a
+ warning on recent gcc versions. Do we need such information
+ to run the audio forawrding?
+
+ chport=&port[0];
+
+ while(*chport!='\0')
+ {
+ in++;
+ local_buf[in]=hex[(*chport >> 4) & 0xf];
+ in++;
+ local_buf[in]=hex[*chport & 0xf];
+ *chport++;
+ }
+*/
+ strcat(local_buf,"00");
+ in+=2;
+
+ while(pszReturnData[i]!='\n')
+ {
+ i++;
+ }
+ }
+ else
+ {
+ in++;
+ local_buf[in]=pszReturnData[i-2];
+ in++;
+ local_buf[in]=pszReturnData[i-1];
+ }
+ }
+
+ in++;
+ local_buf[in]=pszReturnData[i];
+ }
+
+ in++;
+ }
+
+ local_buf[in]=0;
+
+ if (strlen(local_buf))
+ {
+ mcop_local_atom = MakeAtom(mcop_atom, strlen(mcop_atom), 1);
+
+ ChangeWindowProperty(pScreen->root,
+ mcop_local_atom,
+ XA_STRING,
+ iReturnFormat, PropModeReplace,
+ strlen(local_buf), local_buf, 1);
+ }
+
+ free(local_buf);
+ }
+ }
+}
+
+#endif
+
+Bool nxagentReconnectScreen(void *p0)
+{
+ CARD16 w, h;
+ PixmapPtr pPixmap = (PixmapPtr)nxagentDefaultScreen->devPrivate;
+ Mask mask;
+
+#if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_SCREEN_DEBUG)
+ fprintf(stderr, "nxagentReconnectScreen\n");
+#endif
+
+ if (!nxagentOpenScreen(nxagentDefaultScreen, nxagentArgc, nxagentArgv))
+ {
+ return False;
+ }
+
+ nxagentPixmap(pPixmap) = XCreatePixmap(nxagentDisplay,
+ nxagentDefaultWindows[nxagentDefaultScreen->myNum],
+ pPixmap -> drawable.width,
+ pPixmap -> drawable.height,
+ pPixmap -> drawable.depth);
+#ifdef NXAGENT_RECONNECT_SCREEN_DEBUG
+ fprintf(stderr, "nxagentReconnectScreen: recreated %p - ID %lx\n",
+ pPixmap,
+ nxagentPixmap( pPixmap ));
+#endif
+ w = 16;
+ h = 16;
+ (*nxagentDefaultScreen->QueryBestSize)(StippleShape, &w, &h, nxagentDefaultScreen);
+ if (!(nxagentPixmap(nxagentDefaultScreen->PixmapPerDepth[0]) =
+ XCreatePixmap(nxagentDisplay,
+ nxagentDefaultDrawables[1],
+ w,
+ h,
+ 1)));
+
+ nxagentGetDefaultEventMask(&mask);
+ mask |= NXAGENT_KEYBOARD_EVENT_MASK | NXAGENT_POINTER_EVENT_MASK;
+ nxagentSetDefaultEventMask(mask);
+ XSelectInput(nxagentDisplay, nxagentDefaultWindows[0], mask);
+
+ /*
+ * Turn off the screen-saver and reset the
+ * time to the next auto-disconnection.
+ */
+
+ SaveScreens(SCREEN_SAVER_OFF, ScreenSaverActive);
+
+ lastDeviceEventTime.milliseconds = GetTimeInMillis();
+
+ return True;
+}
+
+/* intersect two rectangles */
+Bool intersect(int ax1, int ay1, unsigned int aw, unsigned int ah,
+ int bx1, int by1, unsigned int bw, unsigned int bh,
+ int *x, int *y, unsigned int *w, unsigned int *h)
+{
+ int tx1, ty1, tx2, ty2, ix, iy;
+ unsigned int iw, ih;
+
+ int ax2 = ax1 + aw;
+ int ay2 = ay1 + ah;
+ int bx2 = bx1 + bw;
+ int by2 = by1 + bh;
+
+ /* thanks to http://silentmatt.com/rectangle-intersection */
+
+ /* check if there's any intersection at all */
+ if (ax2 < bx1 || bx2 < ax1 || ay2 < by1 || by2 < ay1) {
+ return FALSE;
+ }
+
+ tx1 = MAX(ax1, bx1);
+ ty1 = MAX(ay1, by1);
+ tx2 = MIN(ax2, bx2);
+ ty2 = MIN(ay2, by2);
+
+ ix = tx1 - ax1;
+ iy = ty1 - ay1;
+ iw = tx2 - tx1;
+ ih = ty2 - ty1;
+
+ /* check if the resulting rectangle is feasible */
+ if (iw <= 0 || ih <= 0) {
+ return FALSE;
+ }
+ *x = ix;
+ *y = iy;
+ *w = iw;
+ *h = ih;
+ return TRUE;
+}
+
+#ifndef NXAGENT_RANDR_XINERAMA_CLIPPING
+/* intersect two rectangles, return aw/ah for w/h if resulting
+ rectangle is (partly) outside of bounding box */
+Bool intersect_bb(int ax1, int ay1, unsigned int aw, unsigned int ah,
+ int bx1, int by1, unsigned int bw, unsigned int bh,
+ int bbx1, int bby1, int bbx2, int bby2,
+ int *x, int *y, unsigned int *w, unsigned int *h)
+{
+ Bool result = intersect(ax1, ay1, aw, ah, bx1, by1, bw, bh, x, y, w, h);
+ if (result == TRUE) {
+ /* check if outside of bounding box */
+ if (ax1 < bbx1 || ax1 + aw > bbx2) {
+ #ifdef DEBUG
+ fprintf(stderr, "intersect: box has parts outside bounding box - width stays unchanged [%d]\n", aw);
+ #endif
+ *w = aw;
+ }
+
+ if (ay1 < bby1 || ay1 + ah > bby2) {
+ #ifdef DEBUG
+ fprintf(stderr, "intersect: box has parts outside bounding box - height stays unchanged [%d]\n", ah);
+ #endif
+ *h = ah;
+ }
+ }
+
+ return result;
+}
+#endif
+
+int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight)
+{
+ ScreenPtr pScreen;
+ /* FIXME: when is this needed? */
+ int doNotify = TRUE;
+ int r;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangeScreenConfig: called for screen [%d], width [%d] height [%d] mmWidth [%d] mmHeight [%d]\n", screen, width, height, mmWidth, mmHeight);
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: screenInfo.screens[%d]->root [%p]\n", screen, (void *) screenInfo.screens[screen]);
+ #endif
+ if (screenInfo.screens[screen]->root == NULL)
+ {
+ return 0;
+ }
+
+ UpdateCurrentTime();
+
+ #ifdef DEBUG
+ if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED)
+ fprintf(stderr, "nxagentChangeScreenConfig: grabstate [SERVER_GRABBED], client [%p]\n", (void *) nxagentGrabServerInfo.client);
+ else if (nxagentGrabServerInfo.grabstate == SERVER_UNGRABBED)
+ fprintf(stderr, "nxagentChangeScreenConfig: grabstate [SERVER_UNGRABBED], client [%p]\n", (void *) nxagentGrabServerInfo.client);
+ else if (nxagentGrabServerInfo.grabstate == CLIENT_PERVIOUS)
+ fprintf(stderr, "nxagentChangeScreenConfig: grabstate [CLIENT_PERVIOUS], client [%p]\n", (void *) nxagentGrabServerInfo.client);
+ else if (nxagentGrabServerInfo.grabstate == CLIENT_IMPERVIOUS)
+ fprintf(stderr, "nxagentChangeScreenConfig: grabstate [CLIENT_IMPERVIOUS], client [%p]\n", (void *) nxagentGrabServerInfo.client);
+ else
+ fprintf(stderr, "nxagentChangeScreenConfig: grabstate [UNKNOWN], client [%p]\n", (void *) nxagentGrabServerInfo.client);
+ #endif
+
+ if (nxagentGrabServerInfo.grabstate == SERVER_GRABBED && nxagentGrabServerInfo.client != NULL)
+ {
+ /*
+ * If any client grabbed the server it won't expect screen
+ * configuration changes until it releases the grab. That could
+ * lead to an X error because available modes are changed
+ * in the meantime.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Cancel with grabbed server (grab held by [%p]).\n", (void *) nxagentGrabServerInfo.client);
+ #endif
+
+ return 0;
+ }
+
+ pScreen = screenInfo.screens[screen] -> root -> drawable.pScreen;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeScreenConfig: Changing config to %d x %d (%dmm x %dmm).\n", width, height, mmWidth, mmHeight);
+ #endif
+
+ r = nxagentResizeScreen(pScreen, width, height, mmWidth, mmHeight);
+
+ if (r != 0)
+ {
+ nxagentAdjustRandRXinerama(pScreen);
+ }
+
+ if (doNotify)
+ {
+ RRScreenSizeNotify(pScreen);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangeScreenConfig: current geometry: %d,%d %dx%d\n", nxagentOption(X), nxagentOption(Y), nxagentOption(Width), nxagentOption(Height));
+ fprintf(stderr, "nxagentChangeScreenConfig: returning [%d]\n", r);
+ #endif
+
+ return r;
+}
+
+/*
+ Destroy an output after removing it from any crtc that might reference it
+ */
+void nxagentDropOutput(RROutputPtr o) {
+ RRCrtcPtr c = o->crtc;
+ if (c) {
+ for (int i = 0; i < c->numOutputs; i++) {
+ if (c->outputs[i] == o) {
+#ifdef DEBUG
+ fprintf(stderr, "nxagentDropOutput: output [%s] is in use by crtc [%p], removing it from there\n", o->name, c);
+#endif
+ RRCrtcSet(c, NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ }
+ }
+ }
+#ifdef DEBUG
+ fprintf(stderr, "nxagentDropOutput: destroying output [%s]\n", o->name);
+#endif
+ RROutputDestroy(o);
+}
+
+int nxagentAdjustRandRXinerama(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+ RROutputPtr output;
+ xRRModeInfo modeInfo;
+ char name[100];
+ int refresh = 60;
+ int width = nxagentOption(Width);
+ int height = nxagentOption(Height);
+
+ pScrPriv = rrGetScrPriv(pScreen);
+
+ if (pScrPriv)
+ {
+ int i;
+ int number = 0;
+
+ XineramaScreenInfo *screeninfo = NULL;
+
+ if (nxagentOption(Xinerama)) {
+ screeninfo = XineramaQueryScreens(nxagentDisplay, &number);
+#ifdef DEBUG
+ if (number) {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: XineramaQueryScreens() returned [%d] screens:\n", number);
+ for (int i=0; i < number; i++) {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: screen_number [%d] x_org [%d] y_org [%d] width [%d] height [%d]\n", screeninfo[i].screen_number, screeninfo[i].x_org, screeninfo[i].y_org, screeninfo[i].width, screeninfo[i].height);
+ }
+
+ }
+ else
+ {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: XineramaQueryScreens() failed - continuing without Xinerama\n");
+ }
+ }
+ else
+ {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: Xinerama is disabled\n");
+#endif
+ }
+
+ /*
+ * if there's no xinerama on the real server or xinerama is
+ * disabled in nxagent we only report one big screen. Clients
+ * still see xinerama enabled but it will report only one (big)
+ * screen. This is consistent with the way rrxinerama always
+ * behaved. The single PanoramiX/Xinerama extension however
+ * disables xinerama if only one screen exists.
+ */
+ if (number == 0) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: faking xinerama\n");
+ #endif
+ number = 1;
+
+ if (screeninfo) {
+ free(screeninfo);
+ }
+ if (!(screeninfo = malloc(sizeof(XineramaScreenInfo)))) {
+ return FALSE;
+ }
+
+ /* fake a xinerama screeninfo that covers the whole screen */
+ screeninfo->screen_number = 0;
+ screeninfo->x_org = nxagentOption(X);
+ screeninfo->y_org = nxagentOption(Y);
+ screeninfo->width = nxagentOption(Width);
+ screeninfo->height = nxagentOption(Height);
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs [%d], numOutputs [%d]\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
+ {
+ Bool rrgetinfo;
+
+ /*
+ * Convert old RANDR 1.0 data (if any) to current structure. This
+ * is needed once at the first run of this function. If we don't
+ * do this here it will be done implicitely later and add mode(s) to
+ * our crtc(s)!
+ */
+ rrgetinfo = RRGetInfo(pScreen, FALSE);
+
+ fprintf(stderr, "nxagentAdjustRandRXinerama: RRGetInfo returned [%d]\n", rrgetinfo);
+ }
+#else
+ /* we are not interested in the return code */
+ RRGetInfo(pScreen, FALSE);
+#endif
+
+#ifndef NXAGENT_RANDR_XINERAMA_CLIPPING
+ /* calculate bounding box (outer edges) */
+ int bbx2, bbx1, bby1, bby2;
+ bbx2 = bby2 = 0;
+ bbx1 = bby1 = INT_MAX;
+
+ for (i = 0; i < number; i++) {
+ bbx2 = MAX(bbx2, screeninfo[i].x_org + screeninfo[i].width);
+ bby2 = MAX(bby2, screeninfo[i].y_org + screeninfo[i].height);
+ bbx1 = MIN(bbx1, screeninfo[i].x_org);
+ bby1 = MIN(bby1, screeninfo[i].y_org);
+ }
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: bounding box: left [%d] right [%d] top [%d] bottom [%d]\n", bbx1, bbx2, bby1, bby2);
+ #endif
+#endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs [%d], numOutputs [%d]\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
+ #endif
+
+ /* adjust the number of CRTCs to match the number of reported
+ xinerama screens on the real server */
+ while (number != pScrPriv->numCrtcs) {
+ if (number < pScrPriv->numCrtcs) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: destroying crtc\n");
+ #endif
+ /* first reset the crtc to free possible outputs, then destroy the crtc */
+ RRCrtcSet(pScrPriv->crtcs[pScrPriv->numCrtcs - 1], NULL, 0, 0, RR_Rotate_0, 0, NULL);
+ RRCrtcDestroy(pScrPriv->crtcs[pScrPriv->numCrtcs - 1]);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: adding crtc\n");
+ #endif
+ RRCrtcCreate(pScreen, NULL);
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: numCrtcs [%d], numOutputs [%d]\n", pScrPriv->numCrtcs, pScrPriv->numOutputs);
+ #endif
+
+ /* set gamma. Currently the only reason for doing this is
+ preventing the xrandr command from complaining about missing
+ gamma. */
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ if (pScrPriv->crtcs[i]->gammaSize == 0) {
+ CARD16 gamma = 0;
+ RRCrtcGammaSetSize(pScrPriv->crtcs[i], 1);
+ RRCrtcGammaSet(pScrPriv->crtcs[i], &gamma, &gamma, &gamma);
+ RRCrtcGammaNotify(pScrPriv->crtcs[i]);
+ }
+ }
+
+ /* delete superfluous non-NX outputs */
+ for (i = pScrPriv->numOutputs - 1; i >= 0; i--)
+ if (strncmp(pScrPriv->outputs[i]->name, "NX", 2))
+ nxagentDropOutput(pScrPriv->outputs[i]);
+
+ /* at this stage only NX outputs are left - we delete the superfluous ones */
+ for (i = pScrPriv->numOutputs - 1; i >= number; i--)
+ nxagentDropOutput(pScrPriv->outputs[i]);
+
+ /* add and init outputs */
+ for (i = 0; i < number; i++) {
+ if (i >= pScrPriv->numOutputs) {
+ sprintf(name, "NX%d", i+1);
+ output = RROutputCreate(pScreen, name, strlen(name), NULL);
+ /* will be done later
+ RROutputSetConnection(output, RR_Disconnected);
+ */
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: created new output [%s]\n", name);
+ #endif
+ }
+ else
+ {
+ output = pScrPriv->outputs[i];
+ }
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: adjusting output [%s]\n", pScrPriv->outputs[i]->name);
+ #endif
+ RROutputSetCrtcs(output, &(pScrPriv->crtcs[i]), 1);
+ /* FIXME: Isn't there a function for setting this? */
+ output->crtc = pScrPriv->crtcs[i];
+ /* FIXME: get SubPixelOrder from real X server */
+ RROutputSetSubpixelOrder(output, SubPixelUnknown);
+ /* FIXME: What is the correct physical size here? */
+ RROutputSetPhysicalSize(output, 0, 0);
+ }
+
+ for (i = 0; i < pScrPriv->numOutputs; i++) {
+ Bool disable_output = FALSE;
+ RRModePtr mymode, prevmode;
+ int new_x, new_y;
+ unsigned int new_w, new_h;
+
+ /*
+ if ((nxagentOption(X) < bbx1 || (nxagentOption(X) + width >= bbx2 )) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: window has parts outside visible area - width stays unchanged [%d]\n", i, pScrPriv->outputs[i]->name, width);
+ #endif
+ new_w = width;
+ }
+
+ if ((nxagentOption(Y) < bby1 || (nxagentOption(Y) + height >= bby2 ) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: window has parts outside visible area - height stays unchanged [%d]\n", i, pScrPriv->outputs[i]->name, height);
+ #endif
+ new_h = height;
+ }
+ */
+
+ /* if there's no intersection disconnect the output */
+#ifdef NXAGENT_RANDR_XINERAMA_CLIPPING
+ disable_output = !intersect(nxagentOption(X), nxagentOption(Y),
+ width, height,
+ screeninfo[i].x_org, screeninfo[i].y_org,
+ screeninfo[i].width, screeninfo[i].height,
+ &new_x, &new_y, &new_w, &new_h);
+#else
+ disable_output = !intersect_bb(nxagentOption(X), nxagentOption(Y),
+ width, height,
+ screeninfo[i].x_org, screeninfo[i].y_org,
+ screeninfo[i].width, screeninfo[i].height,
+ bbx1, bby1, bbx2, bby2,
+ &new_x, &new_y, &new_w, &new_h);
+#endif
+
+ /* save previous mode */
+ prevmode = pScrPriv->crtcs[i]->mode;
+ #ifdef DEBUG
+ if (prevmode) {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: prevmode [%s] ([%p]) refcnt [%d]\n", i, pScrPriv->outputs[i]->name, prevmode->name, (void *)prevmode, prevmode->refcnt);
+ } else {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: no prevmode\n", i, pScrPriv->outputs[i]->name);
+ }
+ #endif
+
+ RROutputSetCrtcs(pScrPriv->outputs[i], &(pScrPriv->crtcs[i]), 1);
+
+ if (disable_output) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: no (valid) intersection - disconnecting\n", i, pScrPriv->outputs[i]->name);
+ #endif
+ RROutputSetConnection(pScrPriv->outputs[i], RR_Disconnected);
+
+ /*
+ * Tests revealed that some window managers (e.g. LXDE) also
+ * take disconnected outputs into account when calculating
+ * stuff like wallpaper tile size and maximum window
+ * size. This is problematic when a disconnected output is
+ * smaller than any of the connected ones. Solution: unset the
+ * mode of the output's crtc. This also leads to xinerama not
+ * showing the disconnected head anymore.
+ */
+ if (prevmode) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: removing mode from output [%d] name [%s]\n", i, pScrPriv->outputs[i]->name);
+ #endif
+ RROutputSetModes(pScrPriv->outputs[i], NULL, 0, 0);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: removing mode from ctrc [%d]\n", i);
+ #endif
+ RRCrtcSet(pScrPriv->crtcs[i], NULL, 0, 0, RR_Rotate_0, 1, &(pScrPriv->outputs[i]));
+ }
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: intersection is x [%d] y [%d] width [%d] height [%d]\n", i, pScrPriv->outputs[i]->name, new_x, new_y, new_w, new_h);
+ #endif
+
+ RROutputSetConnection(pScrPriv->outputs[i], RR_Connected);
+
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+
+#ifdef NXAGENT_RANDR_MODE_PREFIX
+ /* avoid collisions with pre-existing default modes by using a
+ separate namespace. If we'd simply use XxY we could not
+ distinguish between pre-existing modes which should stay
+ and our own modes that should be removed after use. */
+ sprintf(name, "nx_%dx%d", new_w, new_h);
+#else
+ sprintf(name, "%dx%d", new_w, new_h);
+#endif
+
+ modeInfo.width = new_w;
+ modeInfo.height = new_h;
+ modeInfo.hTotal = new_w;
+ modeInfo.vTotal = new_h;
+ modeInfo.dotClock = ((CARD32) new_w * (CARD32) new_h * (CARD32) refresh);
+ modeInfo.nameLength = strlen(name);
+
+ mymode = RRModeGet(&modeInfo, name);
+
+#ifdef DEBUG
+ if (mymode) {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: mode [%s] ([%p]) created/received, refcnt [%d]\n", i, pScrPriv->outputs[i]->name, name, (void *) mymode, mymode->refcnt);
+ }
+ else
+ {
+ /* FIXME: what is the correct behaviour in this case? */
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]: mode [%s] creation failed!\n", i, pScrPriv->outputs[i]->name, name);
+ }
+#endif
+ if (prevmode && mymode == prevmode) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: mymode [%s] ([%p]) == prevmode [%s] ([%p])\n", mymode->name, (void *) mymode, prevmode->name, (void *)prevmode);
+ #endif
+
+ /* if they are the same RRModeGet() has increased the
+ refcnt by 1. We decrease it again by calling only
+ RRModeDestroy() and forget about prevmode */
+ RRModeDestroy(mymode);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: setting mode [%s] ([%p]) refcnt [%d] for output %d [%s]\n", mymode->name, (void *) mymode, mymode->refcnt, i, pScrPriv->outputs[i]->name);
+ #endif
+ RROutputSetModes(pScrPriv->outputs[i], &mymode, 1, 0);
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: setting mode [%s] ([%p]) refcnt [%d] for crtc %d\n", mymode->name, (void *) mymode, mymode->refcnt, i);
+ #endif
+ RRCrtcSet(pScrPriv->crtcs[i], mymode, new_x, new_y, RR_Rotate_0, 1, &(pScrPriv->outputs[i]));
+
+ }
+ } /* if disable_output */
+
+ /* throw away the mode if otherwise unused. We do not need it
+ anymore. We call FreeResource() to ensure the system will not
+ try to free it again on shutdown */
+ if (prevmode && prevmode->refcnt == 1) {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: destroying prevmode [%s]\n", prevmode->name);
+ #endif
+ FreeResource(prevmode->mode.id, 0);
+ }
+
+ RROutputChanged(pScrPriv->outputs[i], TRUE);
+ RRCrtcChanged(pScrPriv->crtcs[i], TRUE);
+ }
+
+ /* release allocated memory */
+ if (screeninfo) {
+ free(screeninfo);
+ screeninfo = NULL;
+ }
+
+#ifdef DEBUG
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRModePtr mode = pScrPriv->crtcs[i]->mode;
+ if (mode) {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: crtc [%d] ([%p]) has mode [%s] ([%p]), refcnt [%d] and [%d] outputs:\n", i, (void *) pScrPriv->crtcs[i], pScrPriv->crtcs[i]->mode->name, (void *)pScrPriv->crtcs[i]->mode, pScrPriv->crtcs[i]->mode->refcnt, pScrPriv->crtcs[i]->numOutputs);
+ }
+ else
+ {
+ fprintf(stderr, "nxagentAdjustRandRXinerama: crtc [%d] ([%p]) has no mode and [%d] outputs:\n", i, (void *) pScrPriv->crtcs[i], pScrPriv->crtcs[i]->numOutputs);
+ }
+
+ if (pScrPriv->crtcs[i]->numOutputs > 0)
+ for (int j=0; j < pScrPriv->crtcs[i]->numOutputs; j++)
+ fprintf(stderr, "nxagentAdjustRandRXinerama: output [%d] name [%s]->crtc=[%p]\n", j, pScrPriv->crtcs[i]->outputs[j]->name, (void *)pScrPriv->crtcs[i]->outputs[j]->crtc);
+ }
+#endif
+
+ pScrPriv -> lastSetTime = currentTime;
+
+ pScrPriv->changed = TRUE;
+ pScrPriv->configChanged = TRUE;
+ }
+
+ /* FIXME: adjust maximum screen size according to remote randr/xinerama setup */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentAdjustRandRXinerama: Min %dx%d, Max %dx%d \n", pScrPriv->minWidth, pScrPriv->minHeight, pScrPriv->maxWidth, pScrPriv->maxHeight);
+ #endif
+
+ return TRUE;
+}
+
+void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin)
+{
+ PixmapPtr pVirtualPixmap;
+ nxagentPrivPixmapPtr pPrivPixmap;
+ XlibGC gc;
+ XGCValues values;
+ int i;
+ int xSrc, ySrc, xDst, yDst, w, h;
+ int nRects;
+ int size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+ BoxRec extents;
+ RegionRec cleanRegion;
+
+ miBSWindowPtr pBackingStore = (miBSWindowPtr) pWin -> backStorage;
+
+ pVirtualPixmap = nxagentVirtualPixmap(pPixmap);
+
+ pPrivPixmap = nxagentPixmapPriv(pPixmap);
+
+ pPrivPixmap -> isBackingPixmap = 1;
+
+ fbCopyWindowProc(&pWin -> drawable, &pVirtualPixmap -> drawable, 0, RegionRects(prgnSave),
+ RegionNumRects(prgnSave), xorg, yorg, FALSE, FALSE, 0, 0);
+
+ values.subwindow_mode = IncludeInferiors;
+
+ gc = XCreateGC(nxagentDisplay, nxagentWindow(screenInfo.screens[0]->root), GCSubwindowMode, &values);
+
+ /*
+ * Initialize to the corrupted region.
+ * Coordinates are relative to the window.
+ */
+
+ RegionInit(&cleanRegion, NullBox, 1);
+
+ RegionCopy(&cleanRegion, nxagentCorruptedRegion((DrawablePtr) pWin));
+
+ /*
+ * Subtract the corrupted region from the saved region.
+ */
+
+ RegionSubtract(&pBackingStore -> SavedRegion, &pBackingStore -> SavedRegion, &cleanRegion);
+
+ /*
+ * Translate the corrupted region. Coordinates
+ * are relative to the backing store pixmap.
+ */
+
+ RegionTranslate(&cleanRegion, -pBackingStore -> x, -pBackingStore -> y);
+
+ /*
+ * Compute the clean region to be saved: subtract
+ * the corrupted region from the region to be saved.
+ */
+
+ RegionSubtract(&cleanRegion, prgnSave, &cleanRegion);
+
+ nRects = RegionNumRects(&cleanRegion);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) malloc(size);
+ pBox = RegionRects(&cleanRegion);
+
+ for (i = nRects; i-- > 0;)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted);
+
+ free((char *) pRects);
+
+ extents = *RegionExtents(&cleanRegion);
+
+ RegionUninit(&cleanRegion);
+
+ xDst = extents.x1;
+ yDst = extents.y1;
+
+/*
+ * Left here the wrong solution. The window could be not
+ * configured yet on the real X, whilst the x and y in the
+ * WindowRec are the new coordinates. The right solution
+ * is the other, as it is independent from the window
+ * coordinates.
+ *
+ * xSrc = xDst + xorg - pWin -> drawable.x;
+ * ySrc = yDst + yorg - pWin -> drawable.y;
+ */
+
+ xSrc = xDst + pBackingStore -> x;
+ ySrc = yDst + pBackingStore -> y;
+
+ w = extents.x2 - extents.x1;
+ h = extents.y2 - extents.y1;
+
+ XCopyArea(nxagentDisplay, nxagentWindow(pWin), nxagentPixmap(pPixmap), gc,
+ xSrc, ySrc, w, h, xDst, yDst);
+
+ nxagentAddItemBSPixmapList(nxagentPixmap(pPixmap), pPixmap, pWin,
+ pBackingStore -> x, pBackingStore -> y);
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentSaveAreas: Added pixmap [%p] with id [%d] on window [%p] to BSPixmapList.\n",
+ (void *) pPixmap, nxagentPixmap(pPixmap), (void *) pWin);
+ #endif
+
+ XFreeGC(nxagentDisplay, gc);
+
+ return;
+}
+
+void nxagentRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg,
+ int yorg, WindowPtr pWin)
+{
+ PixmapPtr pVirtualPixmap;
+ RegionPtr clipRegion;
+ XlibGC gc;
+ XGCValues values;
+ int i;
+ int xSrc, ySrc, xDst, yDst, w, h;
+ int nRects;
+ int size;
+ BoxPtr pBox;
+ XRectangle *pRects;
+ BoxRec extents;
+ miBSWindowPtr pBackingStore;
+
+ /*
+ * Limit the area to restore to the
+ * root window size.
+ */
+
+ RegionIntersect(prgnRestore, prgnRestore,
+ &pWin -> drawable.pScreen -> root -> winSize);
+
+ pBackingStore = (miBSWindowPtr) pWin -> backStorage;
+
+ pVirtualPixmap = nxagentVirtualPixmap(pPixmap);
+
+ fbCopyWindowProc(&pVirtualPixmap -> drawable, &pWin -> drawable, 0, RegionRects(prgnRestore),
+ RegionNumRects(prgnRestore), -xorg, -yorg, FALSE, FALSE, 0, 0);
+
+ values.subwindow_mode = ClipByChildren;
+
+ gc = XCreateGC(nxagentDisplay, nxagentWindow(screenInfo.screens[0]->root), GCSubwindowMode, &values);
+
+ /*
+ * Translate the reference point to the origin of the window.
+ */
+
+ RegionTranslate(prgnRestore,
+ -pWin -> drawable.x - pWin -> borderWidth,
+ -pWin -> drawable.y - pWin -> borderWidth);
+
+ clipRegion = prgnRestore;
+
+ if (nxagentDrawableStatus((DrawablePtr) pPixmap) == NotSynchronized)
+ {
+ clipRegion = RegionCreate(NullBox, 1);
+
+ RegionCopy(clipRegion,
+ nxagentCorruptedRegion((DrawablePtr) pPixmap));
+
+ /*
+ * Translate the reference point to the origin of the window.
+ */
+
+ RegionTranslate(clipRegion,
+ pBackingStore -> x, pBackingStore -> y);
+
+ RegionIntersect(clipRegion, prgnRestore, clipRegion);
+
+ /*
+ * Subtract the corrupted region from the saved areas.
+ * miBSRestoreAreas will return the exposure region.
+ */
+
+ RegionSubtract(&pBackingStore->SavedRegion,
+ &pBackingStore->SavedRegion, clipRegion);
+
+ /*
+ * Store the corrupted region to send expose later.
+ */
+
+ if (nxagentRemoteExposeRegion != NULL)
+ {
+ RegionTranslate(clipRegion, pWin -> drawable.x, pWin -> drawable.y);
+
+ RegionUnion(nxagentRemoteExposeRegion, nxagentRemoteExposeRegion, clipRegion);
+
+ RegionTranslate(clipRegion, -pWin -> drawable.x, -pWin -> drawable.y);
+ }
+
+ /*
+ * Compute the region to be restored.
+ */
+
+ RegionSubtract(clipRegion, prgnRestore, clipRegion);
+ }
+
+ nRects = RegionNumRects(clipRegion);
+ size = nRects * sizeof(*pRects);
+ pRects = (XRectangle *) malloc(size);
+ pBox = RegionRects(clipRegion);
+
+ for (i = nRects; i-- > 0;)
+ {
+ pRects[i].x = pBox[i].x1;
+ pRects[i].y = pBox[i].y1;
+ pRects[i].width = pBox[i].x2 - pBox[i].x1;
+ pRects[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+
+ XSetClipRectangles(nxagentDisplay, gc, 0, 0, pRects, nRects, Unsorted);
+
+ free(pRects);
+
+ extents = *RegionExtents(clipRegion);
+
+ xDst = extents.x1;
+ yDst = extents.y1;
+
+ xSrc = xDst - xorg + pWin -> drawable.x;
+ ySrc = yDst - yorg + pWin -> drawable.y;
+
+ w = extents.x2 - extents.x1;
+ h = extents.y2 - extents.y1;
+
+ nxagentFlushConfigureWindow();
+
+ XCopyArea(nxagentDisplay, nxagentPixmap(pPixmap), nxagentWindow(pWin), gc,
+ xSrc, ySrc, w, h, xDst, yDst);
+
+ XFreeGC(nxagentDisplay, gc);
+
+ if (clipRegion != NULL && clipRegion != prgnRestore)
+ {
+ RegionDestroy(clipRegion);
+ }
+
+ /*
+ * Restore the reference point to the origin of the screen.
+ */
+
+ RegionTranslate(prgnRestore,
+ pWin -> drawable.x - pWin -> borderWidth,
+ pWin -> drawable.y + pWin -> borderWidth);
+
+ return;
+}
+
+void nxagentSetWMNormalHints(int screen)
+{
+ XSizeHints sizeHints;
+
+ /*
+ * Change agent window size and size hints.
+ */
+
+ sizeHints.flags = PPosition | PMinSize | PMaxSize;
+ sizeHints.x = nxagentOption(X);
+ sizeHints.y = nxagentOption(Y);
+
+ sizeHints.min_width = MIN_NXAGENT_WIDTH;
+ sizeHints.min_height = MIN_NXAGENT_HEIGHT;
+
+ sizeHints.width = nxagentOption(Width);
+ sizeHints.height = nxagentOption(Height);
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ }
+ else
+ {
+ sizeHints.max_width = nxagentOption(RootWidth);
+ sizeHints.max_height = nxagentOption(RootHeight);
+ }
+
+ if (nxagentUserGeometry.flag & XValue || nxagentUserGeometry.flag & YValue)
+ {
+ sizeHints.flags |= USPosition;
+ }
+
+ if (nxagentUserGeometry.flag & WidthValue || nxagentUserGeometry.flag & HeightValue)
+ {
+ sizeHints.flags |= USSize;
+ }
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[screen], &sizeHints);
+}
+
+void nxagentShadowAdaptToRatio(void)
+{
+ XSizeHints sizeHints;
+ ScreenPtr pScreen;
+ RegionRec region;
+ BoxRec box;
+
+ pScreen = screenInfo.screens[0];
+
+ nxagentShadowSetRatio(nxagentOption(Width) * 1.0 / nxagentShadowWidth,
+ nxagentOption(Height) * 1.0 / nxagentShadowHeight);
+
+ nxagentShadowCreateMainWindow(pScreen, screenInfo.screens[0]->root, nxagentShadowWidth, nxagentShadowHeight);
+
+ sizeHints.max_width = WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+ sizeHints.max_height = HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay));
+
+ sizeHints.flags = PMaxSize;
+
+ XSetWMNormalHints(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum], &sizeHints);
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = nxagentShadowPixmapPtr -> drawable.width;
+ box.y2 = nxagentShadowPixmapPtr -> drawable.height;
+
+ RegionInit(&region, &box, 1);
+
+ nxagentMarkCorruptedRegion((DrawablePtr)nxagentShadowPixmapPtr, &region);
+
+ RegionUninit(&region);
+}
+
+void nxagentPrintGeometry()
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (nxagentPrintGeometryFlags && (1 << i))
+ {
+ fprintf(stderr, "Info: Screen [%d] resized to geometry [%dx%d] "
+ "fullscreen [%d].\n", i, screenInfo.screens[i] -> width,
+ screenInfo.screens[i] -> height,
+ nxagentOption(Fullscreen));
+ }
+ }
+
+ nxagentPrintGeometryFlags = 0;
+}
+
+#ifdef DUMP
+
+void nxagentShowPixmap(PixmapPtr pPixmap, int x, int y, int width, int height)
+{
+ static int init = 1;
+ static Display *shadow;
+ static Window win;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ WindowPtr pWin = screenInfo.screens[0]->root;
+ unsigned int format;
+ int depth, pixmapWidth, pixmapHeight, length;
+ char *data;
+
+ depth = pPixmap -> drawable.depth;
+ pixmapWidth = pPixmap -> drawable.width;
+ pixmapHeight = pPixmap -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ if (init)
+ {
+ shadow = XOpenDisplay("localhost:0");
+
+ if (shadow == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: WARNING! Shadow display not opened.\n");
+ #endif
+
+ return;
+ }
+
+ init = False;
+ }
+
+ if (win == 0)
+ {
+ win = XCreateSimpleWindow(shadow, DefaultRootWindow(shadow), 0, 0,
+ width, height, 0, 0xFFCC33, 0xFF);
+
+ XSelectInput(shadow, win, StructureNotifyMask);
+
+ XMapWindow(shadow, win);
+
+ for(;;)
+ {
+ XEvent e;
+
+ XNextEvent(shadow, &e);
+
+ if (e.type == MapNotify)
+ {
+ break;
+ }
+ }
+ }
+ else
+ {
+ XResizeWindow(nxagentDisplay, win, width, height);
+ XRaiseWindow(nxagentDisplay, win);
+ }
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: malloc failed.\n");
+ #endif
+
+ return;
+ }
+
+/*
+FIXME
+ image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), x, y,
+ width, height, AllPlanes, format);
+*/
+
+ image = XGetImage(nxagentDisplay, RootWindow(nxagentDisplay, 0), 0, 0,
+ width, height, AllPlanes, format);
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentShowPixmap: XGetImage failed.\n");
+ #endif
+
+ if (data)
+ {
+ free(data);
+ }
+
+ return;
+ }
+
+ fbGetImage((DrawablePtr)pPixmap, 0, 0,
+ width, height, format, AllPlanes, data);
+
+ memcpy(image -> data, data, length);
+
+ value.foreground = 0xffffff;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+
+ gc = XCreateGC(shadow, win, GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask, &value);
+
+ XSync(shadow, 0);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, win, gc, image, 0, 0, 0, 0, width, height);
+
+ XFlush(shadow);
+
+ XFreeGC(shadow, gc);
+
+ if (image != NULL)
+ {
+ XDestroyImage(image);
+ }
+
+ if (data != NULL)
+ {
+ free(data);
+ }
+
+/*
+FIXME
+ if (win != NULL)
+ {
+ XDestroyWindow(shadow, win);
+ }
+*/
+}
+
+void nxagentFbRestoreArea(PixmapPtr pPixmap, WindowPtr pWin, int xSrc, int ySrc, int width,
+ int height, int xDst, int yDst)
+{
+ Display *shadow;
+
+ XlibGC gc;
+ XGCValues value;
+ XImage *image;
+ unsigned int format;
+ int depth, pixmapWidth, pixmapHeight, length;
+ char *data = NULL;
+ Visual *pVisual;
+
+ depth = pPixmap -> drawable.depth;
+ pixmapWidth = pPixmap -> drawable.width;
+ pixmapHeight = pPixmap -> drawable.height;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ shadow = nxagentDisplay;
+
+ length = nxagentImageLength(width, height, format, 0, depth);
+
+ if ((data = malloc(length)) == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: malloc failed.\n");
+ #endif
+
+ return;
+ }
+/*
+ image = XGetImage(nxagentDisplay, nxagentPixmap(pPixmap), xSrc, ySrc,
+ width, height, AllPlanes, format);
+*/
+
+ if (image == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: XGetImage failed.\n");
+ #endif
+
+ if (data)
+ {
+ free(data);
+ }
+
+ return;
+ }
+
+ fbGetImage((DrawablePtr)pPixmap, xSrc, ySrc,
+ width, height, format, AllPlanes, data);
+
+/*
+FIXME
+*/
+ pVisual = nxagentImageVisual((DrawablePtr) pPixmap, depth);
+
+ if (pVisual == NULL)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentFbRestoreArea: WARNING! Visual not found. Using default visual.\n");
+ #endif
+
+ pVisual = nxagentVisuals[nxagentDefaultVisualIndex].visual;
+ }
+
+ image = XCreateImage(nxagentDisplay, pVisual,
+ depth, format, 0, (char *) data,
+ width, height, BitmapPad(nxagentDisplay),
+ nxagentImagePad(width, format, 0, depth));
+/*
+FIXME
+ memcpy(image -> data, data, length);
+*/
+
+ fprintf(stderr, "nxagentFbRestoreArea: Cleaning %d bytes of image.\n", length);
+
+ value.foreground = 0xffffff;
+ value.background = 0x000000;
+ value.plane_mask = 0xffffff;
+ value.fill_style = FillSolid;
+ value.function = GXcopy;
+
+ gc = XCreateGC(shadow, nxagentWindow(screenInfo.screens[0]->root), GCBackground |
+ GCForeground | GCFillStyle | GCPlaneMask | GCFunction, &value);
+
+ NXCleanImage(image);
+
+ XPutImage(shadow, nxagentWindow(pWin), gc, image, 0, 0, xDst, yDst, width, height);
+
+/*
+FIXME
+*/
+ XFlush(shadow);
+
+ XFreeGC(shadow, gc);
+
+ if (image)
+ {
+ XDestroyImage(image);
+ }
+
+/*
+FIXME
+ if (data)
+ {
+ free(data);
+ }
+*/
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Screen.h b/nx-X11/programs/Xserver/hw/nxagent/Screen.h
new file mode 100644
index 000000000..3df586fa8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Screen.h
@@ -0,0 +1,149 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Screen_H__
+#define __Screen_H__
+
+#include "scrnintstr.h"
+
+#define MIN_NXAGENT_WIDTH 80
+#define MIN_NXAGENT_HEIGHT 60
+#define NXAGENT_FRAME_WIDTH 2000
+
+#define nxagentSetPrintGeometry(screen) \
+ nxagentPrintGeometryFlags = (1 << (screen));
+
+extern int nxagentClients;
+
+extern int nxagentAutoDisconnectTimeout;
+
+extern ScreenPtr nxagentDefaultScreen;
+
+extern Pixmap nxagentPixmapLogo;
+
+extern Window nxagentIconWindow;
+
+extern Window nxagentFullscreenWindow;
+
+extern RegionRec nxagentShadowUpdateRegion;
+
+extern WindowPtr nxagentShadowWindowPtr;
+
+extern int nxagentShadowResize;
+
+extern short nxagentShadowUid;
+
+void nxagentSetScreenInfo(ScreenInfo *screenInfo);
+void nxagentSetPixmapFormats(ScreenInfo *screenInfo);
+
+void nxagentPrintGeometry();
+
+extern Window nxagentDefaultWindows[MAXSCREENS];
+extern Window nxagentInputWindows[MAXSCREENS];
+extern Window nxagentScreenSaverWindows[MAXSCREENS];
+
+#ifdef VIEWPORT_FRAME
+
+void nxagentInitViewportFrame(ScreenPtr pScreen, WindowPtr pRootWin);
+
+#else /* #ifdef VIEWPORT_FRAME */
+
+#define nxagentInitViewportFrame(pScreen, pRootWin)
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+Bool nxagentOpenScreen(ScreenPtr pScreen,
+ int argc, char *argv[]);
+
+Bool nxagentCloseScreen(ScreenPtr pScreen);
+
+#define nxagentScreen(window) nxagentDefaultScreen
+
+extern int nxagentBitsPerPixel(int depth);
+
+void nxagentSetScreenSaverTime(void);
+
+void nxagentMinimizeFromFullScreen(ScreenPtr pScreen);
+
+void nxagentMaximizeToFullScreen(ScreenPtr pScreen);
+
+Window nxagentCreateIconWindow(void);
+
+Bool nxagentMagicPixelZone(int x, int y);
+
+Bool nxagentResizeScreen(ScreenPtr pScreen, int width, int height,
+ int mmWidth, int mmHeight);
+
+int nxagentChangeScreenConfig(int screen, int width, int height, int mmWidth, int mmHeight);
+
+int nxagentAdjustRandRXinerama(ScreenPtr pScreen);
+
+extern Bool nxagentReconnectScreen(void *p0);
+
+void nxagentSaveAreas(PixmapPtr pPixmap, RegionPtr prgnSave, int xorg, int yorg, WindowPtr pWin);
+
+void nxagentRestoreAreas(PixmapPtr pPixmap, RegionPtr prgnRestore, int xorg, int yorg, WindowPtr pWin);
+
+extern int monitorResolution;
+
+int nxagentShadowCreateMainWindow( ScreenPtr pScreen, WindowPtr pWin,int width, int height);
+
+int nxagentShadowSendUpdates(int *);
+
+int nxagentShadowPoll(PixmapPtr, GCPtr, unsigned char, int, int, char *, int *, int *);
+
+void nxagentShadowSetWindowsSize(void);
+
+void nxagentSetWMNormalHints(int);
+
+void nxagentShadowSetRatio(float, float);
+
+/*
+ * Change window settings to adapt to a ratio.
+ */
+
+extern void nxagentShadowAdaptToRatio(void);
+
+/*
+ * The pixmap shadowing the real frame buffer.
+ */
+
+extern PixmapPtr nxagentShadowPixmapPtr;
+
+#endif /* __Screen_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Splash.c b/nx-X11/programs/Xserver/hw/nxagent/Splash.c
new file mode 100644
index 000000000..0d3c2ff22
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.c
@@ -0,0 +1,424 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "windowstr.h"
+#include "scrnintstr.h"
+
+#ifdef _XSERVER64
+
+#include "Agent.h"
+
+#define GC XlibGC
+
+#endif /* _XSERVER64 */
+
+#include "Xlib.h"
+#include "Xutil.h"
+
+#include "Display.h"
+#include "Splash.h"
+#include "Screen.h"
+#include "Windows.h"
+#include "Atoms.h"
+#include "Trap.h"
+#include "Init.h"
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Colors used to paint the splash screen.
+ */
+
+int nxagentLogoDepth;
+int nxagentLogoWhite;
+int nxagentLogoRed;
+int nxagentLogoBlack;
+int nxagentLogoGray;
+
+void nxagentPaintLogo(Window win, GC gc, int scale, int width, int height);
+
+/*
+ * From Screen.c.
+ */
+
+extern Atom nxagentWMStart;
+
+/*
+ * From Clipboard.c.
+ */
+
+extern Atom serverCutProperty;
+
+int nxagentShowSplashWindow(Window parentWindow)
+{
+ XWindowAttributes getAttributes;
+ XWindowChanges values;
+ XSetWindowAttributes attributes;
+ GC gc;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShowSplash: Got called.\n");
+ #endif
+
+ #ifdef NXAGENT_TIMESTAMP
+ {
+ extern unsigned long startTime;
+
+ fprintf(stderr, "nxagentShowSplash: Initializing splash start at [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+ #endif
+
+ XSetSelectionOwner(nxagentDisplay, nxagentWMStart, None, CurrentTime);
+
+ nxagentWMPassed = False;
+
+ /*
+ * This would cause a GetWindowAttributes and a
+ * GetGeometry (asynchronous) reply. We use instead
+ * the geometry requested by the user for the agent
+ * window.
+ *
+ * XGetWindowAttributes(nxagentDisplay, parentWindow, &getAttributes);
+ */
+
+ /*
+ * During reconnection we draw the splash over
+ * the default window and not over the root
+ * window because it would be hidden by other
+ * windows.
+ */
+
+ if (nxagentReconnectTrap)
+ {
+ getAttributes.x = nxagentOption(RootX);
+ getAttributes.y = nxagentOption(RootY);
+ }
+ else
+ {
+ getAttributes.x = 0;
+ getAttributes.y = 0;
+ }
+
+ getAttributes.width = nxagentOption(RootWidth);
+ getAttributes.height = nxagentOption(RootHeight);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShowSplash: Going to create new splash window.\n");
+ #endif
+
+ nxagentSplashWindow =
+ XCreateSimpleWindow(nxagentDisplay,
+ parentWindow,
+ getAttributes.x, getAttributes.y,
+ getAttributes.width, getAttributes.height,
+ 0,
+ WhitePixel (nxagentDisplay, 0),
+ BlackPixel (nxagentDisplay, 0));
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentShowSplash: Created new splash window with id [%ld].\n",
+ nxagentSplashWindow);
+ #endif
+
+ gc = XCreateGC(nxagentDisplay, nxagentSplashWindow, 0, NULL);
+ nxagentPaintLogo(nxagentSplashWindow, gc, 1, getAttributes.width, getAttributes.height);
+ XMapRaised (nxagentDisplay, nxagentSplashWindow);
+ values.stack_mode = Above;
+ XConfigureWindow(nxagentDisplay, nxagentSplashWindow, CWStackMode, &values);
+ attributes.override_redirect = True;
+ XChangeWindowAttributes(nxagentDisplay, nxagentSplashWindow, CWOverrideRedirect, &attributes);
+ XFreeGC(nxagentDisplay, gc);
+
+ #ifdef NXAGENT_TIMESTAMP
+ {
+ extern unsigned long startTime;
+ fprintf(stderr, "nxagentShowSplash: Splash ends [%d] milliseconds.\n",
+ GetTimeInMillis() - startTime);
+ }
+ #endif
+
+ return True;
+}
+
+void nxagentPaintLogo(Window win, GC gc, int scale, int width, int height)
+{
+ XPoint rect[4];
+ int w, h, c, w2, h2;
+
+ /*
+ * Show only X2GO Logo when running as X2Go Agent
+ */
+ if(! nxagentX2go)
+ {
+ nxagentPixmapLogo = 0L;
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagenShowtLogo: Got called.\n");
+ #endif
+
+ #ifdef NXAGENT_LOGO_DEBUG
+ fprintf(stderr, "nxagentPaintLogo: begin\n");
+ fprintf(stderr, "nxagentPaintLogo: gen params are: w=%d h=%d d=%d r=%x w=%x b=%x\n",width, height,
+ nxagentLogoDepth, nxagentLogoRed,
+ nxagentLogoWhite, nxagentLogoBlack);
+ #endif
+
+ w = width/scale;
+ h = height/scale;
+
+ w2 = w/2;
+ h2 = h/2;
+
+ if (height > width)
+ {
+ c = w/30;
+ }
+ else
+ {
+ c = w/48;
+ }
+
+ rect[0].x = 0; rect[0].y = 0;
+ rect[1].x = 0; rect[1].y = h;
+ rect[2].x = w; rect[2].y = h;
+ rect[3].x = w; rect[3].y = 0;
+
+ XSetFunction(nxagentDisplay, gc, GXcopy);
+ XSetFillStyle(nxagentDisplay, gc, FillSolid);
+ XSetForeground(nxagentDisplay, gc, nxagentLogoBlack);
+ XSetBackground(nxagentDisplay, gc, nxagentLogoRed);
+
+ nxagentPixmapLogo = XCreatePixmap(nxagentDisplay, win, width, height, nxagentLogoDepth);
+
+ if (!nxagentPixmapLogo)
+ {
+ return;
+ }
+
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ #ifdef NXAGENT_LOGO_DEBUG
+ fprintf(stderr, "filled first poly\n");
+ #endif
+
+ XSetForeground(nxagentDisplay, gc, nxagentLogoRed);
+ XSetBackground(nxagentDisplay, gc, nxagentLogoWhite);
+
+ /*
+ * Draw X2GO Logo
+ */
+
+ /*
+ * Begin 'X'.
+ */
+
+ XSetForeground(nxagentDisplay, gc, nxagentLogoGray);
+ XSetBackground(nxagentDisplay, gc, nxagentLogoWhite);
+ rect[0].x = w2-7*c; rect[0].y = h2-5*c;
+ rect[1].x = w2-8*c; rect[1].y = h2-5*c;
+ rect[2].x = w2-4*c; rect[2].y = h2+3*c;
+ rect[3].x = w2-3*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2-4*c; rect[0].y = h2-5*c;
+ rect[1].x = w2-3*c; rect[1].y = h2-5*c;
+ rect[2].x = w2-7*c; rect[2].y = h2+3*c;
+ rect[3].x = w2-8*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ /*
+ * End 'X'.
+ */
+
+ /*
+ * Start '2'.
+ */
+
+ rect[0].x = w2-2*c; rect[0].y = h2-5*c;
+ rect[1].x = w2-1*c; rect[1].y = h2-5*c;
+ rect[2].x = w2-1*c; rect[2].y = h2-3*c;
+ rect[3].x = w2-2*c; rect[3].y = h2-3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2-2*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+2*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+2*c; rect[2].y = h2-4*c;
+ rect[3].x = w2-2*c; rect[3].y = h2-4*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+1*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+2*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+2*c; rect[2].y = h2-2*c;
+ rect[3].x = w2+1*c; rect[3].y = h2-2*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+2*c; rect[0].y = h2-2*c;
+ rect[1].x = w2+1*c; rect[1].y = h2-2*c;
+ rect[2].x = w2-2*c; rect[2].y = h2+2*c;
+ rect[3].x = w2-1*c; rect[3].y = h2+2*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+
+ rect[0].x = w2-2*c; rect[0].y = h2+2*c;
+ rect[1].x = w2+2*c; rect[1].y = h2+2*c;
+ rect[2].x = w2+2*c; rect[2].y = h2+3*c;
+ rect[3].x = w2-2*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+ /*
+ * End '2'.
+ */
+
+ /*
+ * Start 'G'.
+ */
+
+ rect[0].x = w2+3*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+7*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+7*c; rect[2].y = h2-4*c;
+ rect[3].x = w2+3*c; rect[3].y = h2-4*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+3*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+4*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+4*c; rect[2].y = h2+3*c;
+ rect[3].x = w2+3*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+3*c; rect[0].y = h2+2*c;
+ rect[1].x = w2+7*c; rect[1].y = h2+2*c;
+ rect[2].x = w2+7*c; rect[2].y = h2+3*c;
+ rect[3].x = w2+3*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+6*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+7*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+7*c; rect[2].y = h2-3*c;
+ rect[3].x = w2+6*c; rect[3].y = h2-3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+6*c; rect[0].y = h2-0*c;
+ rect[1].x = w2+7*c; rect[1].y = h2-0*c;
+ rect[2].x = w2+7*c; rect[2].y = h2+3*c;
+ rect[3].x = w2+6*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+5*c; rect[0].y = h2-1*c;
+ rect[1].x = w2+7*c; rect[1].y = h2-1*c;
+ rect[2].x = w2+7*c; rect[2].y = h2+0*c;
+ rect[3].x = w2+5*c; rect[3].y = h2+0*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+ /*
+ * End 'G'.
+ */
+
+ /*
+ * Start 'O'.
+ */
+
+ rect[0].x = w2+8*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+12*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+12*c; rect[2].y = h2-4*c;
+ rect[3].x = w2+8*c; rect[3].y = h2-4*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+8*c; rect[0].y = h2+3*c;
+ rect[1].x = w2+12*c; rect[1].y = h2+3*c;
+ rect[2].x = w2+12*c; rect[2].y = h2+2*c;
+ rect[3].x = w2+8*c; rect[3].y = h2+2*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+8*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+9*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+9*c; rect[2].y = h2+3*c;
+ rect[3].x = w2+8*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ rect[0].x = w2+11*c; rect[0].y = h2-5*c;
+ rect[1].x = w2+12*c; rect[1].y = h2-5*c;
+ rect[2].x = w2+12*c; rect[2].y = h2+3*c;
+ rect[3].x = w2+11*c; rect[3].y = h2+3*c;
+ XFillPolygon(nxagentDisplay, nxagentPixmapLogo, gc, rect, 4, Convex, CoordModeOrigin);
+
+ /*
+ * End 'O'.
+ */
+
+
+ XSetWindowBackgroundPixmap(nxagentDisplay, win, nxagentPixmapLogo);
+
+ #ifdef NXAGENT_LOGO_DEBUG
+ fprintf(stderr, "nxagentPaintLogo: end\n");
+ #endif
+}
+
+void nxagentRemoveSplashWindow(WindowPtr pWin)
+{
+ if (nxagentReconnectTrap) return;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemoveSplashWindow: Destroying the splash window.\n");
+ #endif
+
+ if (!nxagentWMPassed)
+ {
+ XSetSelectionOwner(nxagentDisplay, nxagentWMStart,
+ nxagentDefaultWindows[0], CurrentTime);
+
+ nxagentWMPassed = True;
+ }
+
+ if (nxagentSplashWindow != None)
+ {
+ XDestroyWindow(nxagentDisplay, nxagentSplashWindow);
+
+ nxagentSplashWindow = None;
+ nxagentRefreshWindows(screenInfo.screens[0]->root);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemoveSplashWindow: setting the ownership of %s (%d) on window 0x%lx\n",
+ "NX_CUT_BUFFER_SERVER", (int)serverCutProperty, nxagentWindow(screenInfo.screens[0]->root));
+ #endif
+
+ XSetSelectionOwner(nxagentDisplay, serverCutProperty,
+ nxagentWindow(screenInfo.screens[0]->root), CurrentTime);
+ }
+
+ if (nxagentPixmapLogo)
+ {
+ XFreePixmap(nxagentDisplay, nxagentPixmapLogo);
+
+ nxagentPixmapLogo = (Pixmap) 0;
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Splash.h b/nx-X11/programs/Xserver/hw/nxagent/Splash.h
new file mode 100644
index 000000000..444f1eed0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Splash.h
@@ -0,0 +1,54 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Splash_H__
+#define __Splash_H__
+
+#include "Windows.h"
+#include "X11/Xdmcp.h"
+#include <nx/NXalert.h>
+
+#define XDM_TIMEOUT 20000
+
+extern xdmcp_states XdmcpState;
+extern int XdmcpTimeOutRtx;
+extern int XdmcpStartTime;
+extern int nxagentXdmcpUp;
+
+extern int nxagentLogoDepth;
+extern int nxagentLogoWhite;
+extern int nxagentLogoRed;
+extern int nxagentLogoBlack;
+extern int nxagentLogoGray;
+
+extern Window nxagentSplashWindow;
+
+extern int nxagentWMPassed;
+
+extern int nxagentShowSplashWindow(Window);
+
+extern void nxagentRemoveSplashWindow(WindowPtr pWin);
+
+#endif /* __Splash_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Split.c b/nx-X11/programs/Xserver/hw/nxagent/Split.c
new file mode 100644
index 000000000..9b9691b02
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Split.c
@@ -0,0 +1,1256 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Drawable.h"
+#include "Events.h"
+#include "GCs.h"
+
+#include "compext/Compext.h"
+
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * This should be a macro but for now
+ * we make it a real function to log
+ * a warning in the logs.
+ */
+
+DrawablePtr nxagentSplitDrawable(DrawablePtr pDrawable)
+{
+ if (pDrawable -> type == DRAWABLE_PIXMAP &&
+ nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSplitDrawable: WARNING! The drawable at [%p] is "
+ "virtual. Assuming real at [%p].\n", (void *) pDrawable,
+ (void *) nxagentRealPixmap((PixmapPtr) pDrawable));
+ #endif
+
+ return (DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable);
+ }
+ else
+ {
+ return pDrawable;
+ }
+}
+
+void nxagentInitSplitResources()
+{
+ int resource;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentInitSplitResources: Initializing the split resources.\n");
+ #endif
+
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ pResource -> pending = 0;
+ pResource -> commit = 0;
+ pResource -> split = NXNoResource;
+ pResource -> unpack = NXNoResource;
+ pResource -> drawable = NULL;
+ pResource -> region = NullRegion;
+ pResource -> gc = NULL;
+ }
+}
+
+SplitResourcePtr nxagentAllocSplitResource()
+{
+ int resource;
+
+ SplitResourcePtr pResource;
+
+ for (;;)
+ {
+ resource = NXAllocSplit(nxagentDisplay, NXAnyResource);
+
+ if (resource != NXNoResource)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentAllocSplitResource: Reserving resource [%d] for the next split.\n",
+ resource);
+ #endif
+
+ break;
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentAllocSplitResource: PANIC! No more resources for the next split.\n");
+ #endif
+/*
+FIXME: Must deal with the case all resources are exausted.
+*/
+ FatalError("nxagentAllocSplitResource: PANIC! No more resources for the next split.\n");
+ }
+ }
+
+ pResource = &nxagentSplitResources[resource];
+
+ if (pResource -> pending != 0 || pResource -> split != NXNoResource ||
+ pResource -> unpack != NXNoResource || pResource -> drawable != NULL ||
+ pResource -> region != NullRegion || pResource -> commit != 0 ||
+ pResource -> gc != NULL)
+ {
+ /*
+ * This is really an unrecoverable error.
+ */
+
+ #ifdef PANIC
+ fprintf(stderr, "nxagentAllocSplitResource: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ #endif
+
+ FatalError("nxagentAllocSplitResource: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ }
+
+ pResource -> pending = 1;
+ pResource -> split = resource;
+
+ return pResource;
+}
+
+void nxagentFreeSplitResource(SplitResourcePtr pResource)
+{
+ if (pResource -> pending == 0 || pResource -> split == NXNoResource ||
+ pResource -> drawable != NULL || pResource -> region != NullRegion ||
+ pResource -> gc != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentFreeSplitResource: PANIC! Invalid record provided with values "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ #endif
+
+ FatalError("nxagentFreeSplitResource: PANIC! Invalid record provided with values "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeSplitResource: Clearing the record for resource [%d].\n",
+ pResource -> split);
+ #endif
+
+ NXFreeSplit(nxagentDisplay, pResource -> split);
+
+ pResource -> pending = 0;
+ pResource -> commit = 0;
+ pResource -> split = NXNoResource;
+ pResource -> unpack = NXNoResource;
+ pResource -> drawable = NULL;
+ pResource -> region = NullRegion;
+ pResource -> gc = NULL;
+}
+
+void nxagentInitUnpackResources()
+{
+/*
+FIXME: This must be implemented.
+*/
+}
+
+UnpackResourcePtr nxagentAllocUnpackResource()
+{
+/*
+FIXME: This must be implemented.
+*/
+ return NULL;
+}
+
+void nxagentFreeUnpackResource(UnpackResourcePtr pResource)
+{
+/*
+FIXME: This must be implemented.
+*/
+}
+
+void nxagentReleaseAllSplits(void)
+{
+ int resource;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseAllSplits: Going to release all the split resources.\n");
+ #endif
+
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ if (pResource != NULL && pResource -> pending == 1)
+ {
+ DrawablePtr pDrawable = pResource -> drawable;
+
+ if (pDrawable != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseAllSplits: Releasing the drawable at [%p] for "
+ "resource [%d].\n", (void *) pDrawable, pResource -> split);
+ #endif
+
+ nxagentReleaseSplit(pDrawable);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseAllSplits: Freeing the resource [%d].\n",
+ resource);
+ #endif
+
+ nxagentFreeSplitResource(pResource);
+ }
+ }
+}
+
+/*
+ * Check the coherency of the split record.
+ */
+
+#ifdef TEST
+
+static void nxagentCheckSplit(DrawablePtr pDrawable, SplitResourcePtr pResource)
+{
+ if (pResource == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCheckSplit: PANIC! No record associated to drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ FatalError("nxagentCheckSplit: PANIC! No record associated to drawable at [%p].\n",
+ (void *) pDrawable);
+ }
+ else if (pResource -> drawable != pDrawable ||
+ pResource -> split == NXNoResource)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCheckSplit: PANIC! The record [%d] doesn't match the drawable at [%p].\n",
+ pResource -> split, (void *) pDrawable);
+ #endif
+
+ FatalError("nxagentCheckSplit: PANIC! The record [%d] doesn't match the drawable at [%p].\n",
+ pResource -> split, (void *) pDrawable);
+ }
+ else if (pResource -> commit == 1 &&
+ pResource -> gc == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCheckSplit: PANIC! The record [%d] doesn't have a valid GC.\n",
+ pResource -> split);
+ #endif
+
+ FatalError("nxagentCheckSplit: PANIC! The record [%d] doesn't have a valid GC.\n",
+ pResource -> split);
+ }
+}
+
+static void nxagentCheckResource(SplitResourcePtr pResource, int resource)
+{
+ if (pResource == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCheckResource: PANIC! No record associated to resource [%d].\n",
+ resource);
+ #endif
+
+ FatalError("nxagentCheckResource: PANIC! No record associated to resource [%d].\n",
+ resource);
+ }
+ else if ((pResource -> split != resource || pResource -> pending != 1) ||
+ (pResource -> commit == 1 && (pResource -> drawable == NULL ||
+ pResource -> gc == NULL)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCheckResource: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ #endif
+
+ FatalError("nxagentCheckResource: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ }
+}
+
+#endif
+
+int nxagentCreateSplit(DrawablePtr pDrawable, GCPtr *pGC)
+{
+ SplitResourcePtr pResource;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ pResource = nxagentAllocSplitResource();
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv((PixmapPtr) pDrawable) -> splitResource = pResource;
+ }
+ else
+ {
+ nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource = pResource;
+ }
+
+ pResource -> drawable = pDrawable;
+ pResource -> commit = 1;
+
+ /*
+ * Make a copy of the GC so the client
+ * can safely remove it.
+ */
+
+ pResource -> gc = CreateScratchGC(pDrawable -> pScreen, pDrawable -> depth);
+
+/*
+FIXME: What do we do here?
+*/
+ if (pResource -> gc == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCreateSplit: PANIC! Failed to create split GC for resource [%d].\n",
+ pResource -> split);
+ #endif
+
+ FatalError("nxagentCreateSplit: PANIC! Failed to create split GC for resource [%d].\n",
+ pResource -> split);
+ }
+ else if (CopyGC(*pGC, pResource -> gc, GCFunction | GCPlaneMask |
+ GCSubwindowMode | GCClipXOrigin | GCClipYOrigin |
+ GCClipMask | GCForeground | GCBackground) != Success)
+ {
+/*
+FIXME: What do we do here?
+*/
+ #ifdef PANIC
+ fprintf(stderr, "nxagentCreateSplit: PANIC! Failed to copy split GC for resource [%d].\n",
+ pResource -> split);
+ #endif
+
+ FatalError("nxagentCreateSplit: PANIC! Failed to copy split GC for resource [%d].\n",
+ pResource -> split);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateSplit: Associated GC at [%p] to resource [%d] "
+ "with id [%lu].\n", (void *) pResource -> gc, pResource -> split,
+ (unsigned long) nxagentGC(pResource -> gc));
+ #endif
+
+ *pGC = pResource -> gc;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateSplit: Associated resource [%d] to drawable at [%p].\n",
+ pResource -> split, (void *) pResource -> drawable);
+ #endif
+
+ return pResource -> split;
+}
+
+/*
+ * Set the region to be the current
+ * streaming region.
+ */
+
+void nxagentRegionSplit(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ SplitResourcePtr pResource;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ pResource = nxagentSplitResource(pDrawable);
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentRegionSplit: Associating region to resource [%d] drawable at [%p].\n",
+ pResource -> split, (void *) pDrawable);
+
+ nxagentCheckSplit(pDrawable, pResource);
+
+ #endif
+
+ if (pResource == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentRegionSplit: PANIC! No valid split record for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRegionSplit: Associated region [%d,%d,%d,%d] to drawable at [%p] "
+ "with resource [%d].\n", pRegion -> extents.x1, pRegion -> extents.y1,
+ pRegion -> extents.x2, pRegion -> extents.y2, (void *) pDrawable,
+ pResource -> split);
+ #endif
+
+ pResource -> region = pRegion;
+}
+
+/*
+ * Remove the association between the drawable
+ * and the split resource. The resource is not
+ * deallocated until the end of the split.
+ */
+
+void nxagentReleaseSplit(DrawablePtr pDrawable)
+{
+ SplitResourcePtr pResource;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ pResource = nxagentSplitResource(pDrawable);
+
+ if (pResource == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseSplit: No split resources for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentReleaseSplit: Going to release resource [%d] for drawable at [%p].\n",
+ pResource -> split, (void *) pDrawable);
+
+ nxagentCheckSplit(pDrawable, pResource);
+
+ #endif
+
+ if (pResource -> region != NullRegion)
+ {
+ /*
+ * If we have a region the commits
+ * had to be still valid. In this
+ * case tell the proxy to abort the
+ * data transfer.
+ */
+
+ #ifdef TEST
+
+ if (pResource -> commit == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentReleaseSplit: PANIC! Found a region for resource [%d] but the "
+ "commits are invalid.\n", pResource -> split);
+ #endif
+
+ FatalError("nxagentCheckSplit: PANIC! Found a region for resource [%d] but the "
+ "commits are invalid.\n", pResource -> split);
+ }
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: Aborting the data transfer for resource [%d].\n",
+ pResource -> split);
+ #endif
+
+ NXAbortSplit(nxagentDisplay, pResource -> split);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseSplit: Freeing the region for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ RegionDestroy(pResource -> region);
+
+ pResource -> region = NullRegion;
+ }
+
+ if (pResource -> gc != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseSplit: Freeing the split GC for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ FreeScratchGC(pResource -> gc);
+
+ pResource -> gc = NULL;
+ }
+
+ /*
+ * Remove the association between the
+ * drawable and the resource record.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReleaseSplit: Removing association to drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ nxagentPixmapPriv((PixmapPtr) pDrawable) -> splitResource = NULL;
+ }
+ else
+ {
+ nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource = NULL;
+ }
+
+ /*
+ * Invalidate the commits and remove the
+ * association between the resource and
+ * the drawable.
+ */
+
+ pResource -> drawable = NULL;
+ pResource -> commit = 0;
+}
+
+void nxagentValidateSplit(DrawablePtr pDrawable, RegionPtr pRegion)
+{
+ SplitResourcePtr pResource;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ pResource = nxagentSplitResource(pDrawable);
+
+ if (pResource == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: No split resource for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+ else if (pResource -> region == NullRegion)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: No split region yet for drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+ else if (pResource -> commit == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: WARNING! Split for drawable at [%p] was "
+ "already invalidated.\n", (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentValidateSplit: Going to validate resource [%d] drawable at [%p].\n",
+ pResource -> split, (void *) pDrawable);
+
+ nxagentCheckSplit(pDrawable, pResource);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: Checking the region for resource [%d] "
+ "and drawable at [%p].\n", pResource -> split, (void *) pDrawable);
+ #endif
+
+ /*
+ * If a null region is passed as parameter,
+ * we assume that all the commits have to
+ * be discarded.
+ */
+
+ if (pRegion == NullRegion)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: Forcing all commits as invalid for "
+ "drawable at [%p].\n", (void *) pDrawable);
+ #endif
+
+ nxagentReleaseSplit(pDrawable);
+ }
+ else
+ {
+ RegionRec tmpRegion;
+
+ /*
+ * Check if the provided region overlaps
+ * the area covered by the image being
+ * streamed.
+ */
+
+ RegionInit(&tmpRegion, NullBox, 1);
+
+ RegionIntersect(&tmpRegion, pResource -> region, pRegion);
+
+ if (RegionNil(&tmpRegion) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentValidateSplit: Marking the overlapping commits as invalid "
+ "for drawable at [%p].\n", (void *) pDrawable);
+ #endif
+
+ nxagentReleaseSplit(pDrawable);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentValidateSplit: Leaving the commits as valid for "
+ "drawable at [%p].\n", (void *) pDrawable);
+ }
+ #endif
+
+ RegionUninit(&tmpRegion);
+ }
+}
+
+void nxagentFreeSplit(int resource)
+{
+ DrawablePtr pDrawable;
+
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ if (pResource == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentFreeSplit: PANIC! No valid split record for resource [%d].\n",
+ resource);
+ #endif
+
+ FatalError("nxagentFreeSplit: PANIC! No valid split record for resource [%d].\n",
+ resource);
+ }
+ else if (pResource -> split != resource)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentFreeSplit: PANIC! The record [%d] doesn't match the resource [%d].\n",
+ pResource -> split, resource);
+ #endif
+
+ FatalError("nxagentFreeSplit: PANIC! The record [%d] doesn't match the resource [%d].\n",
+ pResource -> split, resource);
+ }
+
+ pDrawable = pResource -> drawable;
+
+ if (pDrawable != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeSplit: Removing association to drawable at [%p].\n",
+ (void *) pDrawable);
+ #endif
+
+ nxagentReleaseSplit(pDrawable);
+ }
+ #ifdef TEST
+ else
+ {
+ /*
+ * The end of the split has come after we have
+ * invalidated the operation and removed the
+ * association to the drawable. This happens,
+ * for example, if the drawable is destroyed.
+ */
+
+ fprintf(stderr, "nxagentFreeSplit: WARNING! Releasing invalidated resource [%d].\n",
+ pResource -> split);
+ }
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFreeSplit: Freeing the record for resource [%d].\n",
+ pResource -> split);
+ #endif
+
+ nxagentFreeSplitResource(pResource);
+}
+
+/*
+FIXME: This must be enabled when the vanilla
+ synchronization procedure is working.
+*/
+#define USE_FINISH_SPLIT
+
+void nxagentWaitDrawable(DrawablePtr pDrawable)
+{
+ SplitResourcePtr pResource;
+
+ pDrawable = nxagentSplitDrawable(pDrawable);
+
+ pResource = nxagentSplitResource(pDrawable);
+
+ if (pResource == NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWaitDrawable: WARNING! The drawable at [%p] is already awake.\n",
+ (void *) pDrawable);
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWaitDrawable: Waiting drawable at [%p] with resource [%d].\n",
+ (void *) pDrawable, pResource -> split);
+ #endif
+
+ /*
+ * Be sure we intercept an I/O error
+ * as well as an interrupt.
+ */
+
+ #ifdef USE_FINISH_SPLIT
+
+ NXFinishSplit(nxagentDisplay, pResource -> split);
+
+ #endif
+
+ NXFlushDisplay(nxagentDisplay, NXFlushBuffer);
+
+ for (;;)
+ {
+ /*
+ * Handling all the possible events here
+ * preempts the queue and makes a better
+ * use of the link.
+ *
+ * We should better use XIfEvent() instead
+ * of looping again and again through the
+ * event queue.
+ */
+
+ nxagentDispatchEvents(NULL);
+
+ /*
+ * Wait indefinitely until the resource
+ * is released or the display is shut
+ * down.
+ */
+
+ if (nxagentSplitResource(pDrawable) == NULL ||
+ NXDisplayError(nxagentDisplay) == 1)
+ {
+ #ifdef TEST
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ fprintf(stderr, "++++++nxagentWaitDrawable: WARNING! Display error detected while "
+ "waiting for the drawable.\n");
+ }
+ else
+ {
+ fprintf(stderr, "++++++nxagentWaitDrawable: Drawable at [%p] can now be restarted.\n",
+ (void *) pDrawable);
+ }
+
+ #endif
+
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "++++++nxagentWaitDrawable: Yielding control to the NX transport.\n");
+ #endif
+
+ nxagentWaitEvents(nxagentDisplay, NULL);
+ }
+}
+
+static Bool nxagentCommitSplitPredicate(Display *display, XEvent *event, XPointer ptr)
+{
+ return (event -> type == ClientMessage &&
+ event -> xclient.data.l[0] == NXCommitSplitNotify &&
+ event -> xclient.window == 0 && event -> xclient.message_type == 0 &&
+ event -> xclient.format == 32);
+}
+
+void nxagentWaitCommitEvent(int resource)
+{
+ XEvent event;
+
+ /*
+ * Check if there is any commit pending. As
+ * we are at it, handle any commit, even those
+ * commits pertaining to other resources.
+ *
+ * We can receive some commits even if we'll
+ * later receive a no-split event. The proxy,
+ * in fact, may have missed to find the image
+ * in the memory cache and could have loaded it
+ * from disk (so requiring a commit) before we
+ * marked the end of the split sequence.
+ */
+
+ while (nxagentCheckEvents(nxagentDisplay, &event,
+ nxagentCommitSplitPredicate, NULL) == 1)
+ {
+ int client = event.xclient.data.l[1];
+ int request = event.xclient.data.l[2];
+ int position = event.xclient.data.l[3];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitCommitEvent: Commit event received with "
+ "client [%d] request [%d] and position [%d].\n",
+ client, request, position);
+ #endif
+
+ nxagentHandleCommitSplitEvent(client, request, position);
+ }
+}
+
+static Bool nxagentWaitSplitPredicate(Display *display, XEvent *event, XPointer ptr)
+{
+ return (event -> type == ClientMessage &&
+ (event -> xclient.data.l[0] == NXNoSplitNotify ||
+ event -> xclient.data.l[0] == NXStartSplitNotify) &&
+ event -> xclient.window == 0 && event -> xclient.message_type == 0 &&
+ event -> xclient.format == 32);
+}
+
+int nxagentWaitSplitEvent(int resource)
+{
+ XEvent event;
+
+ int split = 0;
+
+ /*
+ * Don't flush the link. We only want to
+ * query the NX transport to check whether
+ * the operation caused a split.
+ */
+
+ NXFlushDisplay(nxagentDisplay, NXFlushBuffer);
+
+ for (;;)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitSplitEvent: Waiting for the split event for resource [%d].\n",
+ resource);
+ #endif
+
+ XIfEvent(nxagentDisplay, &event, nxagentWaitSplitPredicate, NULL);
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitSplitEvent: WARNING! Error detected reading the event.\n");
+ #endif
+
+ nxagentHandleNoSplitEvent(resource);
+
+ break;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWaitSplitEvent: Going to process the split event.\n");
+ #endif
+
+ if (resource != (int) event.xclient.data.l[1])
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentWaitSplitEvent: PANIC! Got event for resource [%d] while "
+ "waiting for resource [%d].\n", (int) event.xclient.data.l[1], resource);
+
+ fprintf(stderr, "nxagentWaitSplitEvent: PANIC! Restarting resource [%d] due to the "
+ "missing split event.\n", resource);
+ #endif
+
+ nxagentHandleNoSplitEvent(resource);
+
+ break;
+ }
+ else if (event.xclient.data.l[0] == NXNoSplitNotify)
+ {
+ nxagentHandleNoSplitEvent(resource);
+
+ break;
+ }
+ else
+ {
+ nxagentHandleStartSplitEvent(resource);
+
+ split = 1;
+
+ break;
+ }
+ }
+
+ return split;
+}
+
+void nxagentHandleNoSplitEvent(int resource)
+{
+ if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ fprintf(stderr, "nxagentHandleNoSplitEvent: Received event for resource [%d].\n",
+ resource);
+
+ nxagentCheckResource(pResource, resource);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleNoSplitEvent: Checking if there is any commit pending.\n");
+ #endif
+
+ nxagentWaitCommitEvent(resource);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleNoSplitEvent: No streaming was required with resource [%d] "
+ "and drawable at [%p].\n", resource, (void *) pResource -> drawable);
+ #endif
+
+ /*
+ * Release the resource.
+ */
+
+ nxagentFreeSplit(resource);
+ }
+ #ifdef PANIC
+ else
+ {
+ fprintf(stderr, "nxagentHandleNoSplitEvent: PANIC! Invalid resource identifier [%d] "
+ " received in event.\n", resource);
+ }
+ #endif
+}
+
+void nxagentHandleStartSplitEvent(int resource)
+{
+ if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ fprintf(stderr, "nxagentHandleStartSplitEvent: Received event for resource [%d].\n",
+ resource);
+
+ nxagentCheckResource(pResource, resource);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleStartSplitEvent: Checking if there is any commit pending.\n");
+ #endif
+
+ nxagentWaitCommitEvent(resource);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleStartSplitEvent: Streaming started with resource [%d] "
+ "and drawable at [%p].\n", resource, (void *) pResource -> drawable);
+ #endif
+ }
+ #ifdef PANIC
+ else
+ {
+ fprintf(stderr, "nxagentHandleStartSplitEvent: PANIC! Invalid resource identifier [%d] "
+ " received in event.\n", resource);
+ }
+ #endif
+}
+
+void nxagentHandleCommitSplitEvent(int resource, int request, int position)
+{
+ if (resource >= 0 && resource < NXNumberOfResources &&
+ request >= 0 && position >= 0)
+ {
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleCommitSplitEvent: Received event for resource [%d].\n",
+ resource);
+ #endif
+
+ if (pResource != NULL && pResource -> commit == 1)
+ {
+ #ifdef TEST
+
+ nxagentCheckResource(pResource, resource);
+
+ fprintf(stderr, "nxagentHandleCommitSplitEvent: Committing request [%d] with "
+ "position [%d] for resource [%d].\n", request, position, resource);
+
+ #endif
+
+ NXCommitSplit(nxagentDisplay, resource, 1, request, position);
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleCommitSplitEvent: Discarding request [%d] for "
+ "resource [%d] with position [%d].\n", request, resource, position);
+ #endif
+
+ NXCommitSplit(nxagentDisplay, resource, 0, request, position);
+ }
+ }
+ #ifdef PANIC
+ else
+ {
+ fprintf(stderr, "nxagentHandleCommitSplitEvent: PANIC! Invalid commit event with "
+ "request [%d] and position [%d] for resource [%d].\n", request,
+ position, resource);
+ }
+ #endif
+}
+
+void nxagentHandleEndSplitEvent(int resource)
+{
+ if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ SplitResourcePtr pResource = &nxagentSplitResources[resource];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleEndSplitEvent: Received event for resource [%d].\n",
+ resource);
+
+ nxagentCheckResource(pResource, resource);
+
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleEndSplitEvent: Checking if there is any commit pending.\n");
+ #endif
+
+ nxagentWaitCommitEvent(resource);
+
+ if (pResource != NULL && pResource -> commit == 1)
+ {
+ #ifdef TEST
+
+ fprintf(stderr, "nxagentHandleEndSplitEvent: Checking the split region at [%p] "
+ "for drawable at [%p].\n", (void *) pResource -> drawable,
+ (void *) pResource -> region);
+
+ if (pResource -> region == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid region [%p] for drawable at [%p].\n",
+ (void *) pResource -> region, (void *) pResource -> drawable);
+ #endif
+
+ FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid region [%p] for drawable at [%p].\n",
+ (void *) pResource -> region, (void *) pResource -> drawable);
+ }
+ else if (pResource -> gc == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid GC [%p] for drawable at [%p].\n",
+ (void *) pResource -> gc, (void *) pResource -> drawable);
+ #endif
+
+ FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid GC [%p] for drawable at [%p].\n",
+ (void *) pResource -> gc, (void *) pResource -> drawable);
+ }
+
+ #endif
+
+ if (pResource -> drawable != NULL &&
+ pResource -> region != NullRegion)
+ {
+ if (RegionNil(pResource -> region) == 0)
+ {
+ RegionSubtract(
+ nxagentCorruptedRegion(pResource -> drawable),
+ nxagentCorruptedRegion(pResource -> drawable),
+ pResource -> region);
+
+/*
+FIXME: Implementing the valid region policy
+
+ nxagentExpandValidRegion(pResource -> drawable, pResource -> region);
+*/
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleEndSplitEvent: Synchronized region [%d,%d,%d,%d] "
+ "for drawable at [%p].\n", pResource -> region -> extents.x1,
+ pResource -> region -> extents.y1, pResource -> region -> extents.x2,
+ pResource -> region -> extents.y2, (void *) pResource -> drawable);
+ #endif
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! The region [%d,%d,%d,%d] for drawable "
+ "at [%p] is empty.\n", pResource -> region -> extents.x1,
+ pResource -> region -> extents.y1, pResource -> region -> extents.x2,
+ pResource -> region -> extents.y2, (void *) pResource -> drawable);
+ #endif
+
+ FatalError("nxagentHandleEndSplitEvent: PANIC! The region [%d,%d,%d,%d] for drawable "
+ "at [%p] is empty.\n", pResource -> region -> extents.x1,
+ pResource -> region -> extents.y1, pResource -> region -> extents.x2,
+ pResource -> region -> extents.y2, (void *) pResource -> drawable);
+ }
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "nxagentHandleEndSplitEvent: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ #endif
+
+ FatalError("nxagentHandleEndSplitEvent: PANIC! Invalid record for resource [%d] with "
+ "pending [%d] split [%d] unpack [%d] drawable [%p] region [%p] commit [%d] gc [%p].\n",
+ resource, pResource -> pending, pResource -> split, pResource -> unpack,
+ (void *) pResource -> drawable, (void *) pResource -> region,
+ pResource -> commit, (void *) pResource -> gc);
+ }
+ }
+
+ /*
+ * Release the resource.
+ */
+
+ nxagentFreeSplit(resource);
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentHandleEndSplitEvent: WARNING! Ignoring split event "
+ "for resource [%d].\n", resource);
+ }
+ #endif
+}
+
+void nxagentHandleEmptySplitEvent()
+{
+/*
+FIXME: Should run a consistency check here.
+*/
+ #ifdef TEST
+ fprintf(stderr, "nxagentHandleEmptySplitEvent: No more split event to handle.\n");
+ #endif
+}
+
+/*
+ * The drawable is going to become corrupted.
+ */
+
+void nxagentSetCorruptedTimestamp(DrawablePtr pDrawable)
+{
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCorruptedTimestamp: Corruption timestamp for pixmap at [%p] was [%lu].\n",
+ (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+
+ nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp = GetTimeInMillis();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCorruptedTimestamp: New corruption timestamp for pixmap at [%p] is [%lu].\n",
+ (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCorruptedTimestamp: Corruption timestamp for window at [%p] was [%lu].\n",
+ (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+
+ nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp = GetTimeInMillis();
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSetCorruptedTimestamp: New corruption timestamp for window at [%p] is [%lu].\n",
+ (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+ }
+ }
+}
+
+/*
+ * Reset the timestamp taken when the drawable
+ * became initially corrupted. The timestamp is
+ * reset only after the drawable has been fully
+ * synchronized.
+ */
+
+void nxagentResetCorruptedTimestamp(DrawablePtr pDrawable)
+{
+ if (nxagentDrawableStatus(pDrawable) == Synchronized)
+ {
+ if (pDrawable -> type == DRAWABLE_PIXMAP)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetCorruptedTimestamp: Corruption timestamp for pixmap at [%p] was [%lu].\n",
+ (void *) pDrawable, nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+
+ nxagentPixmapPriv((PixmapPtr) pDrawable) -> corruptedTimestamp = 0;
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentResetCorruptedTimestamp: Corruption timestamp for window at [%p] was [%lu].\n",
+ (void *) pDrawable, nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp);
+ #endif
+
+ nxagentWindowPriv((WindowPtr) pDrawable) -> corruptedTimestamp = 0;
+ }
+ }
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Split.h b/nx-X11/programs/Xserver/hw/nxagent/Split.h
new file mode 100644
index 000000000..65db133bd
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Split.h
@@ -0,0 +1,92 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Split_H__
+#define __Split_H__
+
+typedef struct _SplitResourceRec
+{
+ int pending;
+ int split;
+ int unpack;
+ DrawablePtr drawable;
+ RegionPtr region;
+ GCPtr gc;
+ int commit;
+
+} SplitResourceRec;
+
+typedef SplitResourceRec *SplitResourcePtr;
+
+extern SplitResourceRec nxagentSplitResources[];
+
+typedef struct _UnpackResourceRec
+{
+ int pending;
+ int unpack;
+ DrawablePtr drawable;
+
+} UnpackResourceRec;
+
+typedef UnpackResourceRec *UnpackResourcePtr;
+
+extern UnpackResourceRec nxagentUnpackResources[];
+
+void nxagentInitSplitResources();
+void nxagentInitUnpackResources();
+
+SplitResourcePtr nxagentAllocSplitResource();
+void nxagentFreeSplitResource(SplitResourcePtr pResource);
+
+UnpackResourcePtr nxagentAllocUnpackResource();
+void nxagentFreeUnpackResource(UnpackResourcePtr pResource);
+
+#define nxagentSplitResource(pDrawable) \
+ ((pDrawable) -> type == DRAWABLE_PIXMAP ? \
+ (nxagentPixmapPriv(nxagentRealPixmap((PixmapPtr) pDrawable)) -> splitResource) : \
+ (nxagentWindowPriv((WindowPtr) pDrawable) -> splitResource))
+
+/*
+FIXME: Make it a real function to log a warning
+ in the logs.
+
+#define nxagentSplitDrawable(pDrawable) \
+ (((pDrawable) -> type == DRAWABLE_PIXMAP && \
+ nxagentPixmapIsVirtual((PixmapPtr) pDrawable)) ? \
+ (DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable) : pDrawable)
+*/
+DrawablePtr nxagentSplitDrawable(DrawablePtr pDrawable);
+
+int nxagentCreateSplit(DrawablePtr pDrawable, GCPtr *pGC);
+void nxagentRegionSplit(DrawablePtr pDrawable, RegionPtr pRegion);
+void nxagentValidateSplit(DrawablePtr pDrawable, RegionPtr pRegion);
+void nxagentReleaseSplit(DrawablePtr pDrawable);
+
+void nxagentReleaseAllSplits(void);
+
+void nxagentSetCorruptedTimestamp(DrawablePtr pDrawable);
+void nxagentResetCorruptedTimestamp(DrawablePtr pDrawable);
+
+#endif /* __Split_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/TestExt.c b/nx-X11/programs/Xserver/hw/nxagent/TestExt.c
new file mode 100644
index 000000000..51a2ecb3d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/TestExt.c
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xproto.h>
+#include <nx-X11/Xlib.h>
+#undef Bool
+#include "screenint.h"
+#include "input.h"
+#include "misc.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "mipointer.h"
+#define XTestSERVER_SIDE
+#include "xtestext1.h"
+
+extern CARD32 nxagentLastEventTime;
+
+void XTestGetPointerPos(short *fmousex, short *fmousey);
+
+void XTestJumpPointer(int jx, int jy, int dev_type);
+
+void XTestGenerateEvent(int dev_type, int keycode, int keystate,
+ int mousex, int mousey);
+
+void XTestGetPointerPos(short *fmousex, short *fmousey)
+{
+ int x,y;
+
+ miPointerPosition(&x, &y);
+ *fmousex = x;
+ *fmousey = y;
+}
+
+void XTestJumpPointer(int jx, int jy, int dev_type)
+{
+ miPointerAbsoluteCursor(jx, jy, GetTimeInMillis());
+}
+
+void XTestGenerateEvent(int dev_type, int keycode, int keystate,
+ int mousex, int mousey)
+{
+/*
+ xEvent tevent;
+
+ tevent.u.u.type = (dev_type == XE_POINTER) ?
+ (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress :
+ (keystate == XTestKEY_UP) ? KeyRelease : KeyPress;
+ tevent.u.u.detail = keycode;
+ tevent.u.keyButtonPointer.rootX = mousex;
+ tevent.u.keyButtonPointer.rootY = mousey;
+ tevent.u.keyButtonPointer.time = nxagentLastEventTime = GetTimeInMillis();
+ mieqEnqueue(&tevent);
+*/
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.c b/nx-X11/programs/Xserver/hw/nxagent/Trap.c
new file mode 100644
index 000000000..c582f6a16
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.c
@@ -0,0 +1,122 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include "Trap.h"
+
+/*
+ * Set if we are dispatching a render
+ * extension request. Used to avoid
+ * reentrancy in GC operations.
+ */
+
+int nxagentGCTrap = 0;
+
+/*
+ * Set if we are enqueing an internal
+ * operation, CreateWindow and Reparent-
+ * Window. Used to remove any screen operation.
+ */
+
+int nxagentScreenTrap = 0;
+
+/*
+ * Set if we detected that our RENDER
+ * implementation is faulty.
+ */
+
+int nxagentRenderTrap = 0;
+
+/*
+ * Set if we are executing a GC operation
+ * only on the X side. Used to avoid
+ * reentrancy in FB layer.
+ */
+
+int nxagentFBTrap = 0;
+
+/*
+ * Set if we are dispatching a shared
+ * memory extension request.
+ */
+
+int nxagentShmTrap = 0;
+
+/*
+ * Set if a shared pixmap operation is
+ * requested by the client.
+ */
+
+int nxagentShmPixmapTrap = 0;
+
+/*
+ * Set if we are dispatching a XVideo
+ * extension request.
+ */
+
+int nxagentXvTrap = 0;
+
+/*
+ * Set if we are dispatching a GLX
+ * extension request.
+ */
+
+int nxagentGlxTrap = 0;
+
+/*
+ * Set while we are resuming the session.
+ */
+
+int nxagentReconnectTrap = 0;
+
+/*
+ * Set if we need to realize a drawable
+ * by using a lossless encoding.
+ */
+
+int nxagentLosslessTrap = 0;
+
+/*
+ * Set to force the synchronization of
+ * a drawable.
+ */
+
+int nxagentSplitTrap = 0;
+
+/*
+ * Set to avoid CapsLock synchronization
+ * problems when CapsLock is the first
+ * key to be pressed in the session.
+ */
+
+int nxagentXkbCapsTrap = 0;
+
+/*
+ * Set to avoid NumLock synchronization
+ * problems when NumLock is the first
+ * key to be pressed in the session.
+ */
+
+int nxagentXkbNumTrap = 0;
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Trap.h b/nx-X11/programs/Xserver/hw/nxagent/Trap.h
new file mode 100644
index 000000000..f0884f657
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Trap.h
@@ -0,0 +1,124 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Traps_H__
+#define __Traps_H__
+
+/*
+ * Set if we are dispatching a render
+ * extension request. Used to avoid
+ * reentrancy in GC operations.
+ */
+
+extern int nxagentGCTrap;
+
+/*
+ * Set if we are enqueing an internal
+ * operation, CreateWindow and Reparent-
+ * Window. Used to remove any screen operation.
+ */
+
+extern int nxagentScreenTrap;
+
+/*
+ * Set if we detected that our RENDER
+ * implementation is faulty.
+ */
+
+extern int nxagentRenderTrap;
+
+/*
+ * Set if we are executing a GC operation
+ * only on the X side. Used to avoid
+ * reentrancy in FB layer.
+ */
+
+extern int nxagentFBTrap;
+
+/*
+ * Set if we are dispatching a shared
+ * memory extension request.
+ */
+
+extern int nxagentShmTrap;
+
+/*
+ * Set if a shared pixmap operation is
+ * requested by the client.
+ */
+
+extern int nxagentShmPixmapTrap;
+
+/*
+ * Set if we are dispatching a XVideo
+ * extension request.
+ */
+
+extern int nxagentXvTrap;
+
+/*
+ * Set if we are dispatching a GLX
+ * extension request.
+ */
+
+extern int nxagentGlxTrap;
+
+/*
+ * Set while we are resuming the session.
+ */
+
+extern int nxagentReconnectTrap;
+
+/*
+ * Set if we need to realize a drawable
+ * by using a lossless encoding.
+ */
+
+extern int nxagentLosslessTrap;
+
+/*
+ * Set to force the synchronization of
+ * a drawable.
+ */
+
+extern int nxagentSplitTrap;
+
+/*
+ * Set to avoid CapsLock synchronization
+ * problems when CapsLock is the first
+ * key to be pressed in the session.
+ */
+
+extern int nxagentXkbCapsTrap;
+
+/*
+ * Set to avoid NumLock synchronization
+ * problems when NumLock is the first
+ * key to be pressed in the session.
+ */
+
+extern int nxagentXkbNumTrap;
+
+#endif /* __Trap_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Utils.h b/nx-X11/programs/Xserver/hw/nxagent/Utils.h
new file mode 100644
index 000000000..8a3335424
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Utils.h
@@ -0,0 +1,55 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Utils_H__
+#define __Utils_H__
+
+/*
+ * Number of bits in fixed point operations.
+ */
+
+#define PRECISION 16
+
+/*
+ * "1" ratio means "don't scale".
+ */
+
+#define DONT_SCALE (1 << PRECISION)
+
+#define nxagentScale(i, ratio) (((i) * (ratio)) >> (PRECISION))
+
+#ifndef MIN
+#define MIN(A, B) ( (A) < (B) ? (A) : (B) )
+#endif
+
+#ifndef MAX
+#define MAX(A, B) ( (A) > (B) ? (A) : (B) );
+#endif
+
+static inline const char * validateString(const char *str) {
+ return str ? str : "(null)";
+}
+
+#endif /* __Utils_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Visual.c b/nx-X11/programs/Xserver/hw/nxagent/Visual.c
new file mode 100644
index 000000000..eebd1fcc1
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.c
@@ -0,0 +1,167 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#include "scrnintstr.h"
+#include "dix.h"
+#include "mi.h"
+#include "mibstore.h"
+#include "resource.h"
+
+#include "X.h"
+#include "Xproto.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Visual.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Predefined visual used for drawables
+ * having a 32 bits depth.
+ */
+
+Visual nxagentAlphaVisual;
+
+Visual *nxagentVisual(VisualPtr pVisual)
+{
+ XVisualInfo visual;
+
+ int i;
+
+ visual.class = pVisual->class;
+ visual.bits_per_rgb = pVisual->bitsPerRGBValue;
+ visual.colormap_size = pVisual->ColormapEntries;
+ visual.depth = pVisual->nplanes;
+ visual.red_mask = pVisual->redMask;
+ visual.green_mask = pVisual->greenMask;
+ visual.blue_mask = pVisual->blueMask;
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ if (nxagentCompareVisuals(visual, nxagentVisuals[i]) == 1)
+ {
+ return nxagentVisuals[i].visual;
+ }
+ }
+
+ return NULL;
+}
+
+Visual *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual)
+{
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ {
+ if (pScreen->visuals[i].vid == visual)
+ {
+ return nxagentVisual(&pScreen->visuals[i]);
+ }
+ }
+
+ return NULL;
+}
+
+Colormap nxagentDefaultVisualColormap(Visual *visual)
+{
+ int i;
+
+ for (i = 0; i < nxagentNumVisuals; i++)
+ {
+ if (nxagentVisuals[i].visual == visual)
+ {
+ return nxagentDefaultColormaps[i];
+ }
+ }
+
+ return None;
+}
+
+/*
+ * This is currently unused. It should serve
+ * the scope of matching a visual whenever
+ * a drawable has a different depth than the
+ * real display.
+ */
+
+Visual *nxagentVisualFromDepth(ScreenPtr pScreen, int depth)
+{
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ {
+ if (pScreen->visuals[i].nplanes == depth)
+ {
+ return nxagentVisual(&pScreen->visuals[i]);
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Create a fake 32 bits depth visual and
+ * initialize it based on the endianess
+ * of the remote display.
+ */
+
+void nxagentInitAlphaVisual()
+{
+ nxagentAlphaVisual.visualid = XAllocID(nxagentDisplay);
+
+ /*
+ * Color masks are referred to bits inside
+ * the pixel. This is independent from the
+ * endianess.
+ */
+
+ nxagentAlphaVisual.red_mask = 0x00ff0000;
+ nxagentAlphaVisual.green_mask = 0x0000ff00;
+ nxagentAlphaVisual.blue_mask = 0x000000ff;
+
+ #ifdef TEST
+ fprintf(stderr,"nxagentInitAlphaVisual: Set alpha visual with id [0x%lx] mask [0x%lx,0x%lx,0x%lx].\n",
+ nxagentAlphaVisual.visualid, nxagentAlphaVisual.red_mask,
+ nxagentAlphaVisual.green_mask, nxagentAlphaVisual.blue_mask);
+ #endif
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Visual.h b/nx-X11/programs/Xserver/hw/nxagent/Visual.h
new file mode 100644
index 000000000..70799f3f8
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Visual.h
@@ -0,0 +1,81 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/*
+
+Copyright 1993 by Davor Matic
+
+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. Davor Matic makes no representations about
+the suitability of this software for any purpose. It is provided "as
+is" without express or implied warranty.
+
+*/
+
+#ifndef __Visual_H__
+#define __Visual_H__
+
+Visual *nxagentVisual(VisualPtr pVisual);
+Visual *nxagentVisualFromID(ScreenPtr pScreen, VisualID visual);
+Visual *nxagentVisualFromDepth(ScreenPtr pScreen, int depth);
+
+Colormap nxagentDefaultVisualColormap(Visual *visual);
+
+#define nxagentDefaultVisual(pScreen) \
+ nxagentVisualFromID((pScreen), (pScreen) -> rootVisual)
+
+/*
+ * Visual generated by Xorg and Xfree86 at
+ * 16-bit depth differs on the bits_per_rgb
+ * value, so we avoid checking it.
+ */
+
+/*
+ * Some Solaris X servers uses the color
+ * masks inverted, so that the red and
+ * the blue mask are switched. To reconnect
+ * the session on this displays, we do a
+ * double check, as workaround.
+ */
+
+#define nxagentCompareVisuals(v1, v2) \
+ ((v1).depth == (v2).depth && \
+ /*(v1).bits_per_rgb == (v2).bits_per_rgb &&*/ \
+ (v1).class == (v2).class && \
+ ((v1).red_mask == (v2).red_mask || \
+ (v1).red_mask == (v2).blue_mask) && \
+ (v1).green_mask == (v2).green_mask && \
+ ((v1).blue_mask == (v2).blue_mask || \
+ (v1).blue_mask == (v2).red_mask) && \
+ (v1).colormap_size == (v2).colormap_size)
+
+Visual nxagentAlphaVisual;
+
+void nxagentInitAlphaVisual();
+
+#endif /* __Visual_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Window.c b/nx-X11/programs/Xserver/hw/nxagent/Window.c
new file mode 100644
index 000000000..23e1d5452
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Window.c
@@ -0,0 +1,3930 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <unistd.h>
+
+#include "X.h"
+#include "Xproto.h"
+#include "gcstruct.h"
+#include "../../include/window.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "region.h"
+#include "dixstruct.h"
+#include "selection.h"
+#include "mi.h"
+#include "fb.h"
+#include "mibstorest.h"
+
+#include "Agent.h"
+#include "Display.h"
+#include "Screen.h"
+#include "GCs.h"
+#include "GCOps.h"
+#include "Drawable.h"
+#include "Colormap.h"
+#include "Cursor.h"
+#include "Visual.h"
+#include "Events.h"
+#include "Clipboard.h"
+#include "Args.h"
+#include "Trap.h"
+#include "Rootless.h"
+#include "Atoms.h"
+#include "Client.h"
+#include "Reconnect.h"
+#include "Dialog.h"
+#include "Splash.h"
+#include "Holder.h"
+#include "Init.h"
+#include "Composite.h"
+#include "Events.h"
+
+#include <nx/NX.h>
+#include "compext/Compext.h"
+
+#include "Xatom.h"
+
+/*
+ * Used to register the window's privates.
+ */
+
+int nxagentWindowPrivateIndex;
+
+/*
+ * Number of windows which need synchronization.
+ */
+
+int nxagentCorruptedWindows;
+
+/*
+ * Used to track nxagent window's visibility.
+ */
+
+int nxagentVisibility = VisibilityUnobscured;
+unsigned long nxagentVisibilityTimeout = 0;
+Bool nxagentVisibilityStop = False;
+
+/*
+ * Set here the required log level.
+ */
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Useful to test the window configuration
+ * failures.
+ */
+
+#ifdef TEST
+#define MAKE_SYNC_CONFIGURE_WINDOW XSync(nxagentDisplay, 0)
+#else
+#define MAKE_SYNC_CONFIGURE_WINDOW
+#endif
+
+extern WindowPtr nxagentViewportFrameLeft;
+extern WindowPtr nxagentViewportFrameRight;
+extern WindowPtr nxagentViewportFrameAbove;
+extern WindowPtr nxagentViewportFrameBelow;
+
+extern WindowPtr nxagentRootTileWindow;
+
+/*
+ * Also referenced in Events.c.
+ */
+
+int nxagentSplashCount = 0;
+
+#define RECTLIMIT 25
+#define BSPIXMAPLIMIT 128
+
+Bool nxagentExposeArrayIsInitialized = False;
+Window nxagentConfiguredSynchroWindow;
+static int nxagentExposeSerial = 0;
+
+StoringPixmapPtr nxagentBSPixmapList[BSPIXMAPLIMIT];
+
+/*
+ * Used to walk through the window hierarchy
+ * to find a window
+ */
+
+typedef struct _WindowMatch
+{
+ WindowPtr pWin;
+ Window id;
+
+} WindowMatchRec;
+
+Bool nxagentReconnectAllWindows(void *);
+
+Bool nxagentDisconnectAllWindows(void);
+
+Bool nxagentIsIconic(WindowPtr);
+
+/*
+ * From NXproperty.c.
+ */
+
+int GetWindowProperty(WindowPtr, Atom, long, long, Bool, Atom, Atom*, int*,
+ unsigned long*, unsigned long*, unsigned char**);
+
+/*
+ * From NXwindow.c.
+ */
+
+void nxagentClearSplash(WindowPtr pWin);
+
+/*
+ * Other local functions.
+ */
+
+static Bool nxagentSomeWindowsAreMapped(void);
+
+static void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what);
+
+static void nxagentTraverseWindow(WindowPtr, void(*)(void *, XID, void *), void *);
+
+static void nxagentDisconnectWindow(void *, XID, void *);
+
+static Bool nxagentLoopOverWindows(void(*)(void *, XID, void *));
+
+static void nxagentReconfigureWindowCursor(void *, XID, void *);
+
+static void nxagentReconnectWindow(void *, XID, void *);
+
+static void nxagentReconfigureWindow(void *, XID, void *);
+
+static int nxagentForceExposure(WindowPtr pWin, void * ptr);
+
+/* by dimbor */
+typedef struct
+{
+ CARD32 state;
+ Window icon;
+}
+nxagentWMStateRec;
+
+/*
+ * This is currently unused.
+ */
+
+#ifdef TEST
+
+static Bool nxagentCheckWindowIntegrity(WindowPtr pWin);
+
+#endif
+
+WindowPtr nxagentGetWindowFromID(Window id)
+{
+ WindowPtr pWin = screenInfo.screens[0]->root;
+
+ while (pWin && nxagentWindowPriv(pWin))
+ {
+ if (nxagentWindow(pWin) == id)
+ {
+ return pWin;
+ }
+
+ if (pWin -> nextSib)
+ {
+ pWin = pWin -> nextSib;
+ }
+ else
+ {
+ pWin = pWin -> firstChild;
+ }
+ }
+
+ return NULL;
+}
+
+static int nxagentFindWindowMatch(WindowPtr pWin, void * ptr)
+{
+ WindowMatchRec *match = (WindowMatchRec *) ptr;
+
+ if (match -> id == nxagentWindow(pWin))
+ {
+ match -> pWin = pWin;
+
+ return WT_STOPWALKING;
+ }
+ else
+ {
+ return WT_WALKCHILDREN;
+ }
+}
+
+WindowPtr nxagentWindowPtr(Window window)
+{
+ int i;
+
+ WindowMatchRec match;
+
+ match.pWin = NullWindow;
+ match.id = window;
+
+ for (i = 0; i < nxagentNumScreens; i++)
+ {
+ WalkTree(screenInfo.screens[i], nxagentFindWindowMatch, (void *) &match);
+
+ if (match.pWin) break;
+ }
+
+ return match.pWin;
+}
+
+Bool nxagentCreateWindow(pWin)
+ WindowPtr pWin;
+{
+ unsigned long mask;
+ XSetWindowAttributes attributes;
+ Visual *visual;
+ ColormapPtr pCmap;
+
+ if (nxagentScreenTrap)
+ {
+ return True;
+ }
+
+ nxagentSplashCount++;
+
+ if (nxagentSplashCount == 2)
+ {
+ nxagentClearSplash(nxagentRootTileWindow);
+ }
+#ifdef NXAGENT_LOGO_DEBUG
+ fprintf(stderr, "nxagentSplashCount: %d\n", nxagentSplashCount);
+#endif
+
+ if (pWin->drawable.class == InputOnly) {
+ mask = CWEventMask;
+ visual = CopyFromParent;
+ }
+ else {
+ mask = CWEventMask | CWBackingStore;
+
+ if (pWin->optional)
+ {
+ mask |= CWBackingPlanes | CWBackingPixel;
+ attributes.backing_planes = pWin->optional->backingBitPlanes;
+ attributes.backing_pixel = pWin->optional->backingPixel;
+ }
+
+ attributes.backing_store = NotUseful;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateWindow: Backing store on window at %p is %d.\n",
+ (void*)pWin, attributes.backing_store);
+ #endif
+
+/*
+FIXME: We need to set save under on the real display?
+*/
+ if (nxagentSaveUnder == True)
+ {
+ mask |= CWSaveUnder;
+ attributes.save_under = False;
+ }
+
+ if (pWin->parent) {
+ if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) {
+ visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
+ mask |= CWColormap;
+ if (pWin->optional->colormap) {
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
+ attributes.colormap = nxagentColormap(pCmap);
+ }
+ else
+ attributes.colormap = nxagentDefaultVisualColormap(visual);
+ }
+ else if (pWin->optional)
+ visual = CopyFromParent;
+ else {
+ visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
+ mask |= CWColormap;
+ attributes.colormap = nxagentDefaultVisualColormap(visual);
+ }
+ }
+ else { /* root windows have their own colormaps at creation time */
+ visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
+ mask |= CWColormap;
+ attributes.colormap = nxagentColormap(pCmap);
+ }
+ }
+
+ if (mask & CWEventMask)
+ {
+ /* Assume that the mask fits in int... broken on Big Endian 64bit systems. */
+ Mask tmp_mask = attributes.event_mask;
+ nxagentGetEventMask(pWin, &tmp_mask);
+ attributes.event_mask = (int)tmp_mask;
+ }
+ #ifdef WARNING
+ else
+ {
+ attributes.event_mask = NoEventMask;
+ }
+ #endif
+
+ /*
+ * Select the event mask if window is a top level
+ * window. This at least makes the keyboard barely
+ * work.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateWindow: Going to create new window.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateWindow: Creating %swindow at %p current event mask = %lX mask & CWEventMask = %ld "
+ "event_mask = %lX\n",
+ nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask,
+ mask & CWEventMask, attributes.event_mask);
+
+ fprintf(stderr, "nxagentCreateWindow: position [%d,%d] size [%d,%d] depth [%d] border [%d] class [%d].\n",
+ pWin->origin.x - wBorderWidth(pWin), pWin->origin.y - wBorderWidth(pWin),
+ pWin->drawable.width, pWin->drawable.height, pWin->drawable.depth, pWin->borderWidth,
+ pWin->drawable.class);
+ #endif
+
+ nxagentWindowPriv(pWin)->window = XCreateWindow(nxagentDisplay,
+ nxagentWindowParent(pWin),
+ pWin->origin.x -
+ wBorderWidth(pWin),
+ pWin->origin.y -
+ wBorderWidth(pWin),
+ pWin->drawable.width,
+ pWin->drawable.height,
+ pWin->borderWidth,
+ pWin->drawable.depth,
+ pWin->drawable.class,
+ visual,
+ mask, &attributes);
+
+ nxagentWindowPriv(pWin) -> isMapped = 0;
+ nxagentWindowPriv(pWin) -> isRedirected = 0;
+
+ nxagentWindowPriv(pWin) -> visibilityState = VisibilityUnobscured;
+
+ nxagentWindowPriv(pWin) -> corruptedRegion = RegionCreate(NULL, 1);
+
+ nxagentWindowPriv(pWin) -> hasTransparentChildren = 0;
+
+ nxagentWindowPriv(pWin) -> containGlyphs = 0;
+
+ nxagentWindowPriv(pWin) -> corruptedId = 0;
+
+ nxagentWindowPriv(pWin) -> deferredBackgroundExpose = 0;
+
+ nxagentWindowPriv(pWin) -> synchronizationBitmap = NullPixmap;
+
+ nxagentWindowPriv(pWin) -> corruptedTimestamp = 0;
+
+ nxagentWindowPriv(pWin) -> splitResource = NULL;
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ if (pWin != nxagentRootlessWindow)
+ {
+ WindowPtr pParent = pWin -> parent;
+
+ if (pParent && nxagentWindowPriv(pParent) -> isMapped == 1)
+ {
+ nxagentWindowPriv(pWin) -> isMapped = 1;
+ }
+ else
+ {
+ nxagentWindowPriv(pWin) -> isMapped = 0;
+ }
+ }
+ else
+ {
+ nxagentWindowPriv(pWin) -> isMapped = 0;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentCreateWindow: Created new window with id [%ld].\n",
+ nxagentWindowPriv(pWin)->window);
+ #endif
+
+ /*
+ * Set the WM_DELETE_WINDOW protocols on every
+ * top level window. Also redirect the window
+ * if it is a top level.
+ */
+
+ if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
+ {
+ Atom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True);
+
+ XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True);
+
+ XSetWMProtocols(nxagentDisplay, nxagentWindowPriv(pWin)->window, &atom, 1);
+
+ nxagentAddPropertyToList(prop, pWin);
+
+ /*
+ * Redirect the window to the off-screen
+ * memory, if the composite extension is
+ * supported on the display.
+ */
+/*
+FIXME: Do all the windows for which nxagentWindowTopLevel(pWin)
+ returns true need to be redirected?
+*/
+ nxagentRedirectWindow(pWin);
+ }
+
+ nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
+ nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
+ nxagentWindowPriv(pWin)->width = pWin->drawable.width;
+ nxagentWindowPriv(pWin)->height = pWin->drawable.height;
+ nxagentWindowPriv(pWin)->borderWidth = pWin->borderWidth;
+ nxagentWindowPriv(pWin)->siblingAbove = None;
+ nxagentWindowPriv(pWin)->pPicture = NULL;
+
+ if (nxagentRootTileWindow)
+ {
+ if (nxagentWindowPriv(pWin)->window != nxagentWindowPriv(nxagentRootTileWindow)->window)
+ {
+ XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow)->window);
+ }
+ }
+
+ if (pWin->nextSib)
+ {
+ nxagentWindowPriv(pWin->nextSib)->siblingAbove = nxagentWindow(pWin);
+ }
+
+#ifdef NXAGENT_SHAPE2
+#ifdef SHAPE
+ nxagentWindowPriv(pWin)->boundingShape = NULL;
+ nxagentWindowPriv(pWin)->clipShape = NULL;
+#endif /* SHAPE */
+#else
+#ifdef SHAPE
+ nxagentWindowPriv(pWin)->boundingShape = RegionCreate(NULL, 1);
+ nxagentWindowPriv(pWin)->clipShape = RegionCreate(NULL, 1);
+#endif /* SHAPE */
+#endif
+
+ fbCreateWindow(pWin);
+
+ /*
+ * Only the root window will have
+ * the right colormap.
+ */
+
+ if (!pWin->parent)
+ {
+ nxagentSetInstalledColormapWindows(pWin->drawable.pScreen);
+ }
+
+ return True;
+}
+
+Bool nxagentSomeWindowsAreMapped()
+{
+ WindowPtr pWin = screenInfo.screens[0]->root -> firstChild;
+
+ while (pWin)
+ {
+ if ((pWin -> mapped || nxagentIsIconic(pWin)) &&
+ pWin -> drawable.class == InputOutput)
+ {
+ return True;
+ }
+
+ pWin = pWin -> nextSib;
+ }
+
+ return False;
+}
+
+Bool nxagentDestroyWindow(WindowPtr pWin)
+{
+ int i;
+ int j;
+
+ nxagentPrivWindowPtr pWindowPriv;
+
+ if (nxagentScreenTrap == 1)
+ {
+ return 1;
+ }
+
+ nxagentClearClipboard(NULL, pWin);
+
+ for (j = 0; j < nxagentExposeQueue.length; j++)
+ {
+ i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
+
+ if (nxagentExposeQueue.exposures[i].pWindow == pWin)
+ {
+ if (nxagentExposeQueue.exposures[i].localRegion != NullRegion)
+ {
+ RegionDestroy(nxagentExposeQueue.exposures[i].localRegion);
+ }
+
+ nxagentExposeQueue.exposures[i].localRegion = NullRegion;
+
+ if (nxagentExposeQueue.exposures[i].remoteRegion != NullRegion)
+ {
+ RegionDestroy(nxagentExposeQueue.exposures[i].remoteRegion);
+ }
+
+ nxagentExposeQueue.exposures[i].remoteRegion = NullRegion;
+ }
+ }
+
+ nxagentDeleteConfiguredWindow(pWin);
+
+ pWindowPriv = nxagentWindowPriv(pWin);
+
+ if (pWin->nextSib)
+ {
+ nxagentWindowPriv(pWin->nextSib)->siblingAbove =
+ pWindowPriv->siblingAbove;
+ }
+
+ #ifdef NXAGENT_SHAPE2
+
+ #ifdef SHAPE
+
+ if (pWindowPriv->boundingShape)
+ {
+ RegionDestroy(
+ pWindowPriv->boundingShape);
+ }
+
+ if (pWindowPriv->clipShape)
+ {
+ RegionDestroy(
+ pWindowPriv->clipShape);
+ }
+
+ #endif
+
+ #else
+
+ RegionDestroy(
+ pWindowPriv->boundingShape);
+
+ RegionDestroy(
+ pWindowPriv->clipShape);
+
+ #endif
+
+ if (pWindowPriv -> corruptedRegion)
+ {
+ RegionDestroy(
+ pWindowPriv -> corruptedRegion);
+
+ pWindowPriv -> corruptedRegion = NULL;
+ }
+
+ if (nxagentSynchronization.pDrawable == (DrawablePtr) pWin)
+ {
+ nxagentSynchronization.pDrawable = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyWindow: Synchronization drawable [%p] removed from resources.\n",
+ (void *) pWin);
+ #endif
+ }
+
+ nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
+
+ nxagentDestroyDrawableBitmap((DrawablePtr) pWin);
+
+ if (pWindowPriv -> splitResource != NULL)
+ {
+ nxagentReleaseSplit((DrawablePtr) pWin);
+ }
+
+ XDestroyWindow(nxagentDisplay, nxagentWindow(pWin));
+
+ if (nxagentOption(Rootless))
+ {
+ nxagentRootlessDelTopLevelWindow(pWin);
+ }
+
+ nxagentSplashCount--;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentDestroyWindow: The splash counter is now [%d].\n",
+ nxagentSplashCount);
+ #endif
+
+ if (nxagentSplashCount == 1)
+ {
+ XClearWindow(nxagentDisplay, nxagentWindowPriv(nxagentRootTileWindow) -> window);
+ }
+
+ if (pWin == nxagentRootTileWindow)
+ {
+ nxagentWindowPriv(nxagentRootTileWindow)->window = None;
+
+ nxagentRootTileWindow = None;
+ }
+
+ pWindowPriv->window = None;
+
+ if (pWin -> optional)
+ {
+ pWin -> optional -> userProps = NULL;
+ }
+
+ if (nxagentOption(Rootless) && nxagentRootlessDialogPid == 0 &&
+ nxagentLastWindowDestroyed == False && nxagentSomeWindowsAreMapped() == False)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentDestroyWindow: Last mapped window as been destroyed.\n");
+ #endif
+
+ nxagentLastWindowDestroyed = True;
+ nxagentLastWindowDestroyedTime = GetTimeInMillis();
+ }
+
+ return True;
+}
+
+Bool nxagentPositionWindow(WindowPtr pWin, int x, int y)
+{
+ if (nxagentScreenTrap == 1)
+ {
+ return True;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentPositionWindow: Changing position of window [%p][%ld] to [%d,%d].\n",
+ (void *) pWin, nxagentWindow(pWin), x, y);
+ #endif
+
+ nxagentAddConfiguredWindow(pWin, CWParent | CWX | CWY | CWWidth |
+ CWHeight | CWBorderWidth);
+
+ return True;
+}
+
+void nxagentRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
+{
+ if (nxagentScreenTrap == 1)
+ {
+ return;
+ }
+
+ nxagentAddConfiguredWindow(pWin, CW_RootlessRestack);
+
+}
+
+void nxagentSwitchFullscreen(ScreenPtr pScreen, Bool switchOn)
+{
+ XEvent e;
+
+ if (nxagentOption(Rootless) == 1)
+ {
+ return;
+ }
+
+ if (switchOn == 0)
+ {
+ nxagentWMDetect();
+
+ /*
+ * The smart scheduler could be stopped while
+ * waiting for the reply. In this case we need
+ * to yield explicitly to avoid to be stuck in
+ * the dispatch loop forever.
+ */
+
+ isItTimeToYield = 1;
+
+ if (nxagentWMIsRunning == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Can't switch to window mode, no window manager "
+ "has been detected.\n");
+ #endif
+
+ return;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentSwitchFullscreen: Switching to %s mode.\n",
+ switchOn ? "fullscreen" : "windowed");
+ #endif
+
+ nxagentChangeOption(Fullscreen, switchOn);
+
+ memset(&e, 0, sizeof(e));
+
+ e.xclient.type = ClientMessage;
+ e.xclient.message_type = nxagentAtoms[13]; /* _NET_WM_STATE */
+ e.xclient.display = nxagentDisplay;
+ e.xclient.window = nxagentDefaultWindows[pScreen -> myNum];
+ e.xclient.format = 32;
+ e.xclient.data.l[0] = nxagentOption(Fullscreen) ? 1 : 0;
+ e.xclient.data.l[1] = nxagentAtoms[14]; /* _NET_WM_STATE_FULLSCREEN */
+
+ XSendEvent(nxagentDisplay, DefaultRootWindow(nxagentDisplay), False,
+ SubstructureRedirectMask, &e);
+
+ if (switchOn == 1)
+ {
+ nxagentFullscreenWindow = nxagentDefaultWindows[pScreen -> myNum];
+
+ nxagentGrabPointerAndKeyboard(NULL);
+ }
+ else
+ {
+ nxagentFullscreenWindow = None;
+
+ nxagentUngrabPointerAndKeyboard(NULL);
+ }
+}
+
+void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn)
+{
+ Window w;
+ XSetWindowAttributes attributes;
+ unsigned long valuemask;
+
+ if (nxagentOption(Rootless))
+ {
+ return;
+ }
+
+ if (!switchOn)
+ {
+ nxagentWMDetect();
+
+ if (!nxagentWMIsRunning)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "Warning: Can't switch to window mode, no window manager has been detected.\n");
+ #endif
+
+ return;
+ }
+ }
+
+ w = nxagentDefaultWindows[pScreen -> myNum];
+ attributes.override_redirect = switchOn;
+ valuemask = CWOverrideRedirect;
+ XUnmapWindow(nxagentDisplay, w);
+ XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes);
+
+ XReparentWindow(nxagentDisplay, w, DefaultRootWindow(nxagentDisplay), 0, 0);
+
+ if (switchOn)
+ {
+ /*
+ * Change to fullscreen mode.
+ */
+
+ struct timeval timeout;
+ int i;
+ XEvent e;
+
+ /*
+ * Wait for window manager reparenting the default window.
+ */
+
+ for (i = 0; i < 100 && nxagentWMIsRunning; i++)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentSwitchAllScreens: WARNING! Going to wait for the ReparentNotify event.\n");
+ #endif
+
+ if (XCheckTypedWindowEvent(nxagentDisplay, w, ReparentNotify, &e))
+ {
+ break;
+ }
+
+ /*
+ * This should also flush
+ * the NX link for us.
+ */
+
+ XSync(nxagentDisplay, 0);
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50 * 1000;
+
+ nxagentWaitEvents(nxagentDisplay, &timeout);
+ }
+
+ if (i < 100)
+ {
+ /*
+ * The window manager has done with the reparent
+ * operation. We can resize and map the window.
+ */
+
+ nxagentChangeOption(Fullscreen, True);
+ nxagentChangeOption(AllScreens, True);
+
+
+ /*
+ * Save the window-mode configuration.
+ */
+
+ nxagentChangeOption(SavedX, nxagentOption(X));
+ nxagentChangeOption(SavedY, nxagentOption(Y));
+ nxagentChangeOption(SavedWidth, nxagentOption(Width));
+ nxagentChangeOption(SavedHeight, nxagentOption(Height));
+ nxagentChangeOption(SavedRootWidth, nxagentOption(RootWidth));
+ nxagentChangeOption(SavedRootHeight, nxagentOption(RootHeight));
+
+ /*
+ * Reconf the Default window.
+ */
+
+ nxagentChangeOption(X, 0);
+ nxagentChangeOption(Y, 0);
+ nxagentChangeOption(Width, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+ nxagentChangeOption(Height, HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)));
+
+ /*
+ * Move the root window.
+ */
+
+ nxagentChangeOption(RootX, (nxagentOption(Width) - nxagentOption(RootWidth)) / 2);
+ nxagentChangeOption(RootY, (nxagentOption(Height) - nxagentOption(RootHeight)) / 2);
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y),
+ nxagentOption(Width), nxagentOption(Height));
+
+ nxagentUpdateViewportFrame(0, 0, nxagentOption(RootWidth), nxagentOption(RootHeight));
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ /*
+ * We disable the screensaver when changing
+ * mode to fullscreen. Is it really needed?
+ */
+
+ XSetScreenSaver(nxagentDisplay, 0, 0, DefaultExposures, DefaultBlanking);
+
+ if (nxagentIconWindow == None)
+ {
+ nxagentIconWindow = nxagentCreateIconWindow();
+
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+ }
+
+ XMapRaised(nxagentDisplay, w);
+ XSetInputFocus(nxagentDisplay, w, RevertToParent, CurrentTime);
+ XCheckTypedWindowEvent(nxagentDisplay, w, LeaveNotify, &e);
+ nxagentFullscreenWindow = w;
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ if (nxagentOption(Shadow) == 0)
+ {
+ nxagentChangeScreenConfig(0, WidthOfScreen(DefaultScreenOfDisplay(nxagentDisplay)),
+ HeightOfScreen(DefaultScreenOfDisplay(nxagentDisplay)), 0, 0);
+ }
+ else
+ {
+ nxagentShadowAdaptToRatio();
+ }
+ }
+ }
+ else
+ {
+ /*
+ * We have waited for a reparent event unsuccessfully.
+ * Something happened to the window manager.
+ */
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSwitchAllScreens: WARNING! Expected ReparentNotify event missing.\n");
+ #endif
+
+ nxagentWMIsRunning = False;
+ attributes.override_redirect = False;
+ XChangeWindowAttributes(nxagentDisplay, w, valuemask, &attributes);
+ XMapWindow(nxagentDisplay, w);
+ }
+ }
+ else
+ {
+ /*
+ * FIXME:
+ * It could be necessary:
+ * - To restore screensaver.
+ * - To set or reset nxagentForceBackingStore flag.
+ * - To propagate device settings to the X server if no WM is running.
+ */
+
+ /*
+ * Change to windowed mode.
+ */
+
+ nxagentChangeOption(Fullscreen, False);
+ nxagentChangeOption(AllScreens, False);
+
+ XDestroyWindow(nxagentDisplay, nxagentIconWindow);
+
+ nxagentIconWindow = nxagentFullscreenWindow = None;
+
+ if (nxagentOption(DesktopResize) == 1)
+ {
+ nxagentChangeOption(RootWidth, nxagentOption(SavedRootWidth));
+ nxagentChangeOption(RootHeight, nxagentOption(SavedRootHeight));
+
+ if (nxagentOption(Shadow) == 0)
+ {
+ nxagentChangeScreenConfig(0, nxagentOption(RootWidth),
+ nxagentOption(RootHeight), 0, 0);
+ }
+ }
+
+ if (nxagentOption(WMBorderWidth) > 0 && nxagentOption(WMTitleHeight) > 0)
+ {
+ nxagentChangeOption(X, nxagentOption(SavedX) -
+ nxagentOption(WMBorderWidth));
+ nxagentChangeOption(Y, nxagentOption(SavedY) -
+ nxagentOption(WMTitleHeight));
+ }
+ else
+ {
+ nxagentChangeOption(X, nxagentOption(SavedX));
+ nxagentChangeOption(Y, nxagentOption(SavedY));
+ }
+
+ nxagentChangeOption(Width, nxagentOption(SavedWidth));
+ nxagentChangeOption(Height, nxagentOption(SavedHeight));
+
+ if (nxagentOption(Shadow) == 1 && nxagentOption(DesktopResize) == 1)
+ {
+ nxagentShadowAdaptToRatio();
+ }
+
+ XMoveResizeWindow(nxagentDisplay, w, nxagentOption(X), nxagentOption(Y),
+ nxagentOption(Width), nxagentOption(Height));
+
+ nxagentUpdateViewportFrame(0, 0, nxagentOption(Width), nxagentOption(Height));
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root), 0, 0);
+ XMapWindow(nxagentDisplay, w);
+
+ nxagentChangeOption(RootX, 0);
+ nxagentChangeOption(RootY, 0);
+ }
+
+ XMoveResizeWindow(nxagentDisplay, nxagentInputWindows[0], 0, 0,
+ nxagentOption(Width), nxagentOption(Height));
+
+ nxagentSetPrintGeometry(pScreen -> myNum);
+}
+
+#ifdef VIEWPORT_FRAME
+
+void nxagentUpdateViewportFrame(int x, int y, int w, int h)
+{
+ /*
+ * Four virtual windows make a frame around the viewport. We move the frame
+ * with the viewport together. The areas going into the viewport were covered by
+ * the frame and become exposed. This make the agent send expose events to his
+ * clients.
+ */
+
+ XID values[3];
+ Mask mask;
+
+ /*
+ * nxagentScreenTrap = True;
+ */
+
+ values[2] = Above;
+
+ values[1] = nxagentOption(RootHeight);
+
+ mask = CWX | CWHeight | CWStackMode;
+ values[0] = x - NXAGENT_FRAME_WIDTH;
+ ConfigureWindow(nxagentViewportFrameLeft, mask, (XID *) &values, serverClient);
+
+ values[0] = x + w;
+ ConfigureWindow(nxagentViewportFrameRight, mask, (XID *) &values, serverClient);
+
+ values[1] = nxagentOption(RootWidth);
+
+ mask = CWY | CWWidth | CWStackMode;
+ values[0] = y - NXAGENT_FRAME_WIDTH;
+ ConfigureWindow(nxagentViewportFrameAbove, mask, (XID *) &values, serverClient);
+
+ values[0] = y + h;
+ ConfigureWindow(nxagentViewportFrameBelow, mask, (XID *) &values, serverClient);
+
+ /*
+ * nxagentScreenTrap = False;
+ */
+}
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+void nxagentMoveViewport(ScreenPtr pScreen, int hShift, int vShift)
+{
+ int newX;
+ int newY;
+ int oldX;
+ int oldY;
+
+ Bool doMove = False;
+ oldX = 0;
+ oldY = 0;
+
+ if (nxagentOption(Rootless))
+ {
+ return;
+ }
+
+ /*
+ * We must keep x coordinate between viewportXSpan and zero, if viewportXSpan
+ * is less then zero. If viewportXSpan is greater or equal to zero, it means
+ * the agent root window has a size smaller than the agent default window.
+ * In this case we keep the old coordinate.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMoveViewport: RootX[%i] RootY[%i], hShift[%i] vShift[%i].\n",
+ nxagentOption(RootX), nxagentOption(RootY), hShift, vShift);
+ #endif
+
+ nxagentChangeOption(ViewportXSpan, nxagentOption(Width) - nxagentOption(RootWidth));
+
+ nxagentChangeOption(ViewportYSpan, nxagentOption(Height) - nxagentOption(RootHeight));
+
+ if (nxagentOption(ViewportXSpan) < 0)
+ {
+ newX = nxagentOption(RootX) - hShift;
+
+ if (newX > 0)
+ {
+ newX = 0;
+ }
+ else if (newX < nxagentOption(ViewportXSpan))
+ {
+ newX = nxagentOption(ViewportXSpan);
+ }
+ }
+ else if (nxagentOption(ViewportXSpan) == 0)
+ {
+ newX = 0;
+ }
+ else
+ {
+ newX = nxagentOption(RootX);
+ }
+
+ if (nxagentOption(ViewportYSpan) < 0)
+ {
+ newY = nxagentOption(RootY) - vShift;
+
+ if (newY > 0)
+ {
+ newY = 0;
+ }
+ else if (newY < nxagentOption(ViewportYSpan))
+ {
+ newY = nxagentOption(ViewportYSpan);
+ }
+ }
+ else if (nxagentOption(ViewportYSpan) == 0)
+ {
+ newY = 0;
+ }
+ else
+ {
+ newY = nxagentOption(RootY);
+ }
+
+ oldX = nxagentOption(RootX);
+
+ if (newX != nxagentOption(RootX))
+ {
+ nxagentChangeOption(RootX, newX);
+
+ doMove = True;
+ }
+
+ oldY = nxagentOption(RootY);
+
+ if (newY != nxagentOption(RootY))
+ {
+ nxagentChangeOption(RootY, newY);
+
+ doMove = True;
+ }
+
+ if (doMove)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMoveViewport: New viewport geometry: (%d, %d)-"
+ "(%d, %d)\n", -nxagentOption(RootX), -nxagentOption(RootY),
+ -nxagentOption(RootX) + nxagentOption(Width),
+ -nxagentOption(RootY) + nxagentOption(Height));
+
+ fprintf(stderr, "nxagentMoveViewport: Root geometry x=[%d] y=[%d]\n",
+ pScreen->root -> drawable.x,
+ pScreen->root -> drawable.y );
+ #endif
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(pScreen->root),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ if (nxagentOption(ClientOs) == ClientOsWinnt)
+ {
+ /*
+ * If doMove is True we add exposed rectangles
+ * to the remote expose region. This is done to
+ * refresh the areas showed newly in the viewport.
+ * We create two rectangles, one for horizontal
+ * pan and one for vertical pan.
+ */
+
+ BoxRec hRect;
+ BoxRec vRect;
+
+ hRect.x1 = -newX;
+ hRect.y1 = -newY;
+
+ if (hShift < 0)
+ {
+ hRect.x2 = -oldX;
+ hRect.y2 = -newY + nxagentOption(Height);
+ }
+ else if (hShift > 0)
+ {
+ hRect.x1 = -oldX + nxagentOption(Width);
+ hRect.x2 = -newX + nxagentOption(Width);
+ hRect.y2 = -newY + nxagentOption(Height);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMoveViewport: hRect p1[%i, %i] - p2[%i, %i].\n", hRect.x1, hRect.y1, hRect.x2, hRect.y2);
+ #endif
+
+ vRect.x1 = -newX;
+ vRect.y1 = -newY;
+
+ if (vShift < 0)
+ {
+ vRect.x2 = -newX + nxagentOption(Width);
+ vRect.y2 = -oldY;
+ }
+ else if (vShift > 0)
+ {
+ vRect.y1 = -oldY + nxagentOption(Height);
+ vRect.x2 = -newX + nxagentOption(Width);
+ vRect.y2 = -newY + nxagentOption(Height);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentMoveViewport: vRect p1[%i, %i] - p2[%i, %i].\n", vRect.x1, vRect.y1, vRect.x2, vRect.y2);
+ #endif
+
+ if (oldX != newX && hRect.x1 != hRect.x2 && hRect.y1 != hRect.y2)
+ {
+ nxagentAddRectToRemoteExposeRegion(&hRect);
+ }
+
+ if (oldY != newY && vRect.x1 != vRect.x2 && vRect.y1 != vRect.y2)
+ {
+ nxagentAddRectToRemoteExposeRegion(&vRect);
+ }
+ }
+ }
+
+ nxagentUpdateViewportFrame(-nxagentOption(RootX), -nxagentOption(RootY),
+ nxagentOption(Width), nxagentOption(Height));
+}
+
+void nxagentConfigureWindow(WindowPtr pWin, unsigned int mask)
+{
+ unsigned int valuemask;
+ XWindowChanges values;
+ int offX, offY;
+ int i, j;
+
+ offX = nxagentWindowPriv(pWin)->x - pWin->origin.x;
+ offY = nxagentWindowPriv(pWin)->y - pWin->origin.y;
+
+ if (nxagentScreenTrap == 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: WARNING: Called with the screen trap set.\n");
+ #endif
+
+ return;
+ }
+
+ if (nxagentOption(Rootless) == 1 &&
+ nxagentWindowTopLevel(pWin) == 1)
+ {
+ mask &= ~(CWSibling | CWStackMode);
+ }
+ else
+ {
+ if (mask & CW_RootlessRestack)
+ {
+ mask = CWStackingOrder;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Called with window [%p][%ld] and mask [%x].\n",
+ (void *) pWin, nxagentWindow(pWin), mask);
+ #endif
+
+ nxagentMoveCorruptedRegion(pWin, mask);
+
+ valuemask = 0;
+
+ if (mask & CW_Update)
+ {
+ mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackingOrder;
+ }
+
+ if (mask & CWX)
+ {
+ valuemask |= CWX;
+
+ values.x = nxagentWindowPriv(pWin)->x = pWin->origin.x - wBorderWidth(pWin);
+ }
+
+ if (mask & CWY)
+ {
+ valuemask |= CWY;
+
+ values.y = nxagentWindowPriv(pWin)->y = pWin->origin.y - wBorderWidth(pWin);
+ }
+
+ if (mask & CWWidth)
+ {
+ valuemask |= CWWidth;
+
+ values.width = nxagentWindowPriv(pWin)->width = pWin->drawable.width;
+ }
+
+ if (mask & CWHeight)
+ {
+ valuemask |= CWHeight;
+
+ values.height = nxagentWindowPriv(pWin)->height = pWin->drawable.height;
+ }
+
+ if (mask & CWBorderWidth)
+ {
+ valuemask |= CWBorderWidth;
+
+ values.border_width = nxagentWindowPriv(pWin)->borderWidth =
+ pWin->borderWidth;
+ }
+
+ if (mask & CW_Update)
+ {
+ valuemask = 0;
+ }
+
+ if (valuemask)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Going to configure window [%p][%ld] with mask [%x].\n",
+ (void *) pWin, nxagentWindow(pWin), valuemask);
+ #endif
+
+ if (pWin->bitGravity == StaticGravity &&
+ ((mask & CWX) || (mask & CWY)) &&
+ ((mask & CWWidth) || (mask & CWHeight)))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Window has StaticGravity. Going to translate Expose events by offset [%d, %d].\n",
+ offX, offY);
+ #endif
+
+ nxagentAddStaticResizedWindow(pWin, XNextRequest(nxagentDisplay), offX, offY);
+
+ for (j = 0; j < nxagentExposeQueue.length; j++)
+ {
+ i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
+
+ if (nxagentExposeQueue.exposures[i].pWindow == pWin &&
+ nxagentExposeQueue.exposures[i].remoteRegion != NullRegion)
+ {
+ RegionTranslate(nxagentExposeQueue.exposures[i].remoteRegion, offX, offY);
+ }
+ }
+ }
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pWin), valuemask, &values);
+
+ MAKE_SYNC_CONFIGURE_WINDOW;
+ }
+
+ if (mask & CWStackingOrder &&
+ nxagentWindowPriv(pWin)->siblingAbove != nxagentWindowSiblingAbove(pWin))
+ {
+ WindowPtr pSib;
+
+ /*
+ * Find the top sibling.
+ */
+
+ for (pSib = pWin; pSib->prevSib != NullWindow; pSib = pSib->prevSib);
+
+ /*
+ * Configure the top sibling.
+ */
+
+ valuemask = CWStackMode;
+
+ values.stack_mode = Above;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Going to configure top sibling [%ld] "
+ "with mask [%x] and parent [%ld].\n", nxagentWindow(pSib),
+ valuemask, nxagentWindowParent(pWin));
+ #endif
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values);
+
+ MAKE_SYNC_CONFIGURE_WINDOW;
+
+ nxagentWindowPriv(pSib)->siblingAbove = None;
+
+ /*
+ * Configure the rest of siblings.
+ */
+
+ valuemask = CWSibling | CWStackMode;
+
+ values.stack_mode = Below;
+
+ for (pSib = pSib->nextSib; pSib != NullWindow; pSib = pSib->nextSib)
+ {
+ values.sibling = nxagentWindowSiblingAbove(pSib);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Going to configure other sibling [%ld] "
+ "with mask [%x] and parent [%ld] below [%ld].\n", nxagentWindow(pSib),
+ valuemask, nxagentWindowParent(pWin), nxagentWindowSiblingAbove(pSib));
+ #endif
+
+ XConfigureWindow(nxagentDisplay, nxagentWindow(pSib), valuemask, &values);
+
+ MAKE_SYNC_CONFIGURE_WINDOW;
+
+ nxagentWindowPriv(pSib)->siblingAbove = nxagentWindowSiblingAbove(pSib);
+ }
+
+ #ifdef TEST
+ {
+ Window root_return;
+ Window parent_return;
+ Window *children_return;
+ unsigned int nchildren_return;
+ Window *pw;
+ Status result;
+
+ result = XQueryTree(nxagentDisplay, DefaultRootWindow(nxagentDisplay),
+ &root_return, &parent_return, &children_return, &nchildren_return);
+
+ if (result)
+ {
+ pw = children_return;
+
+ fprintf(stderr, "nxagentConfigureWindow: Children of the root: ");
+ while(nchildren_return > 0)
+ {
+ pSib = nxagentWindowPtr(children_return[--nchildren_return]);
+ if (pSib)
+ {
+ fprintf(stderr, "%lu ", children_return[nchildren_return]);
+ }
+ }
+ fprintf(stderr, "\n");
+
+ if (children_return)
+ {
+ XFree(children_return);
+ }
+ }
+ else
+ {
+ fprintf(stderr, "nxagentConfigureWindow: Failed QueryTree request.\n ");
+ }
+ }
+ #endif
+ }
+
+ #ifdef NXAGENT_SPLASH
+
+ /*
+ * This should bring again the splash window
+ * on top, so why the else clause? Is this
+ * really needed?
+ *
+ *
+ * else if (mask & CWStackingOrder)
+ * {
+ * if (nxagentSplashWindow)
+ * {
+ * valuemask = CWStackMode;
+ *
+ * values.stack_mode = Above;
+ *
+ * #ifdef TEST
+ * fprintf(stderr, "nxagentConfigureWindow: Going to configure splash window [%ld].\n",
+ * nxagentSplashWindow);
+ * #endif
+ *
+ * XConfigureWindow(nxagentDisplay, nxagentSplashWindow, valuemask, &values);
+ *
+ * MAKE_SYNC_CONFIGURE_WINDOW;
+ * }
+ * }
+ */
+
+ #endif
+
+ if (mask & CW_RootlessRestack)
+ {
+ if (!pWin -> prevSib)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Raising window [%p][%ld].\n",
+ (void *) pWin, nxagentWindow(pWin));
+ #endif
+
+ XRaiseWindow(nxagentDisplay, nxagentWindow(pWin));
+ }
+ else if (!pWin -> nextSib)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Lowering window [%p][%ld].\n",
+ (void *) pWin, nxagentWindow(pWin));
+ #endif
+
+ XLowerWindow(nxagentDisplay, nxagentWindow(pWin));
+ }
+ else
+ {
+ XlibWindow windowList[2];
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentConfigureWindow: Putting window [%p][%ld] in the middle.\n",
+ (void *) pWin, nxagentWindow(pWin));
+ #endif
+
+ windowList[0] = nxagentWindow(pWin->prevSib);
+ windowList[1] = nxagentWindow(pWin);
+
+ XRestackWindows(nxagentDisplay, windowList, 2);
+ }
+ }
+
+ #ifdef SHAPE
+
+ if (mask & CW_Shape)
+ {
+ nxagentShapeWindow(pWin);
+ }
+
+ #endif
+
+ if (mask & CW_Map &&
+ (!nxagentOption(Rootless) ||
+ nxagentRootlessWindow != pWin))
+ {
+ XMapWindow(nxagentDisplay, nxagentWindow(pWin));
+
+ return;
+ }
+}
+
+void nxagentReparentWindow(pWin, pOldParent)
+ WindowPtr pWin;
+ WindowPtr pOldParent;
+{
+ if (nxagentScreenTrap)
+ {
+ return;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReparentWindow: window at %p [%lx] previous parent at %p [%lx].\n",
+ (void*)pWin, nxagentWindow(pWin),
+ (void*)pOldParent, nxagentWindow(pOldParent));
+ #endif
+
+ XReparentWindow(nxagentDisplay, nxagentWindow(pWin),
+ nxagentWindowParent(pWin),
+ pWin->origin.x - wBorderWidth(pWin),
+ pWin->origin.y - wBorderWidth(pWin));
+}
+
+Bool nxagentChangeWindowAttributes(pWin, mask)
+ WindowPtr pWin;
+ unsigned long mask;
+{
+ XSetWindowAttributes attributes;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeWindowAttributes: Changing attributes for window at [%p] with mask [%lu].\n",
+ (void *) pWin, mask);
+ #endif
+
+ if (nxagentScreenTrap)
+ {
+ return True;
+ }
+
+ if (mask & CWBackPixmap)
+ {
+ switch (pWin->backgroundState)
+ {
+ case None:
+ {
+ attributes.background_pixmap = None;
+ attributes.background_pixel = nxagentWhitePixel;
+
+ /*
+ * One of problems faced during the implementation of lazy
+ * encoding policies was due to the presence of windows with
+ * transparent background, usually created by X clients to
+ * cover some sensible areas (i.e. checkboxes used by
+ * Konqueror 3.5). The sequence of operations consists in
+ * drawing the underneath part before covering it with the
+ * transparent window, so when we synchronize the deferred
+ * drawing operation we have to bear in mind that the dest-
+ * ination area is covered by a window. By using the Inclu-
+ * deInferiors GC's property and by clipping the region to
+ * synchronize to the borderClip instead of clipList (to
+ * include the areas covered by children) we can easily take
+ * care of this situation, but there is a drawback: if the
+ * children are not transparent, we are going to synchronize
+ * invisible areas. To avoid this we have added the 'has-
+ * TransparentChildren' flag, which is set when a window has
+ * at least one child with background None. The problem is
+ * that we don't know when to reset the flag. This solution,
+ * also, doesn't take care of transparent windows which don't
+ * have childhood relationships with underneath windows.
+ * We tried to mark the whole windows as dirty when they are
+ * created to force the synchronization of transparent windows
+ * with the content of underneath windows, but, of course,
+ * this works only with the first synchronization because the
+ * transparent windows will be never marked again as dirty.
+ */
+
+ if (pWin -> parent != NULL)
+ {
+ nxagentWindowPriv(pWin -> parent) -> hasTransparentChildren = 1;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Window at [%p] got the "
+ "hasTransparentChildren flag.\n", (void *) pWin);
+ #endif
+ }
+
+ break;
+ }
+ case ParentRelative:
+ {
+ attributes.background_pixmap = ParentRelative;
+
+ break;
+ }
+ case BackgroundPixmap:
+ {
+ /*
+ * If a window background is corrupted, we grant
+ * its usability by clearing it with a solid co-
+ * lor. When the pixmap will be fully synchroni-
+ * zed, an expose will be sent to the window's
+ * hierarchy.
+ */
+
+ if (nxagentDrawableStatus((DrawablePtr) pWin -> background.pixmap) == NotSynchronized)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeWindowAttributes: The window at [%p] has the background at [%p] "
+ "not synchronized.\n", (void *) pWin, (void *) pWin -> background.pixmap);
+ #endif
+
+ if (nxagentIsCorruptedBackground(pWin -> background.pixmap) == 0)
+ {
+ nxagentIsCorruptedBackground(pWin -> background.pixmap) = 1;
+
+ nxagentAllocateCorruptedResource((DrawablePtr) pWin -> background.pixmap, RT_NX_CORR_BACKGROUND);
+
+ /*
+ * Clearing the remote background to
+ * make it usable.
+ */
+
+ nxagentFillRemoteRegion((DrawablePtr) pWin -> background.pixmap,
+ nxagentCorruptedRegion((DrawablePtr) pWin -> background.pixmap));
+ }
+ }
+
+ attributes.background_pixmap = nxagentPixmap(pWin -> background.pixmap);
+
+ break;
+ }
+ case BackgroundPixel:
+ {
+ mask &= ~CWBackPixmap;
+
+ break;
+ }
+ }
+ }
+
+ if (mask & CWBackPixel)
+ {
+ if (pWin -> backgroundState == BackgroundPixel)
+ {
+ attributes.background_pixel = nxagentPixel(pWin -> background.pixel);
+ }
+ else
+ {
+ mask &= ~CWBackPixel;
+ }
+ }
+
+ if (mask & CWBorderPixmap)
+ {
+ if (pWin -> borderIsPixel != 0)
+ {
+ mask &= ~CWBorderPixmap;
+ }
+ else
+ {
+ attributes.border_pixmap = nxagentPixmap(pWin -> border.pixmap);
+ }
+ }
+
+ if (mask & CWBorderPixel)
+ {
+ if (pWin -> borderIsPixel != 0)
+ {
+ attributes.border_pixel = nxagentPixel(pWin -> border.pixel);
+ }
+ else
+ {
+ mask &= ~CWBorderPixel;
+ }
+ }
+
+ if (mask & CWBitGravity)
+ {
+ attributes.bit_gravity = pWin -> bitGravity;
+ }
+
+ /*
+ * As we set this bit, whe must change dix in
+ * order not to perform PositionWindow and let
+ * X move children windows for us.
+ */
+
+ if (mask & CWWinGravity)
+ {
+ attributes.win_gravity = pWin -> winGravity;
+ }
+
+/*
+FIXME: Do we need to set the attribute on the
+ remote display?
+*/
+ if (mask & CWBackingStore)
+ {
+ attributes.backing_store = pWin -> backingStore;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentChangeWindowAttributes: Changing backing store value to %d"
+ " for window at %p.\n", pWin -> backingStore, (void*)pWin);
+ #endif
+ }
+
+ if (mask & CWBackingPlanes)
+ {
+ if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL))
+ {
+ mask &= ~CWBackingPlanes;
+ }
+ else
+ {
+ attributes.backing_planes = pWin -> optional -> backingBitPlanes;
+ }
+ }
+
+ if (mask & CWBackingPixel)
+ {
+ if ((nxagentBackingStore == NotUseful) || (pWin -> optional == NULL))
+ {
+ mask &= ~CWBackingPixel;
+ }
+ else
+ {
+ attributes.backing_pixel = pWin -> optional -> backingPixel;
+ }
+ }
+
+ if (mask & CWOverrideRedirect)
+ {
+ attributes.override_redirect = pWin -> overrideRedirect;
+ }
+
+/*
+FIXME: Do we need to set the attribute on the
+ remote display?
+*/
+ if (mask & CWSaveUnder)
+ {
+ attributes.save_under = pWin -> saveUnder;
+ }
+
+ /*
+ * Events are handled elsewhere.
+ */
+
+ if (mask & CWEventMask)
+ {
+ mask &= ~CWEventMask;
+ }
+
+ if (mask & CWDontPropagate)
+ {
+ mask &= ~CWDontPropagate;
+ }
+
+ if (mask & CWColormap)
+ {
+ ColormapPtr pCmap;
+
+ pCmap = (ColormapPtr) LookupIDByType(wColormap(pWin), RT_COLORMAP);
+
+/*
+FIXME: When the caller is nxagentReconfigureWindow
+ sometimes wColormap(pWin) is 0. Could a window
+ have no colormap?
+*/
+ if (pCmap != NULL)
+ {
+ attributes.colormap = nxagentColormap(pCmap);
+
+ nxagentSetInstalledColormapWindows(pWin -> drawable.pScreen);
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentChangeWindowAttributes: WARNING! Bad colormap "
+ "[%lu] for window at [%p].\n", wColormap(pWin), (void *) pWin);
+ #endif
+
+ mask &= ~CWColormap;
+ }
+ }
+
+ if (mask & CWCursor)
+ {
+ if (nxagentOption(Rootless))
+ {
+ if (pWin->cursorIsNone == 0 && pWin->optional != NULL &&
+ pWin->optional->cursor != NULL && nxagentCursorPriv(pWin ->
+ optional -> cursor, pWin -> drawable.pScreen) != NULL)
+ {
+ attributes.cursor = nxagentCursor(pWin -> optional -> cursor,
+ pWin -> drawable.pScreen);
+ }
+ else
+ {
+ attributes.cursor = None;
+ }
+ }
+ else
+ {
+ /*
+ * This is handled in cursor code
+ */
+
+ mask &= ~CWCursor;
+ }
+ }
+
+ if (mask != 0)
+ {
+ XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), mask, &attributes);
+ }
+
+ return 1;
+}
+
+Bool nxagentRealizeWindow(WindowPtr pWin)
+{
+ if (nxagentScreenTrap == 1)
+ {
+ return True;
+ }
+
+ /*
+ * Not needed.
+ *
+ * nxagentConfigureWindow(pWin, CWStackingOrder);
+ *
+ * nxagentFlushConfigureWindow();
+ */
+
+ nxagentAddConfiguredWindow(pWin, CWStackingOrder);
+ nxagentAddConfiguredWindow(pWin, CW_Shape);
+
+ /* add by dimbor */
+ if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
+ {
+ Atom prop = MakeAtom("WM_STATE", strlen("WM_STATE"), True);
+ nxagentWMStateRec wmState;
+ wmState.state = 1; /* NormalState */
+ wmState.icon = None;
+ if (ChangeWindowProperty(pWin, prop, prop, 32, 0, 2, &wmState, 1) != Success)
+ fprintf(stderr, "nxagentRealizeWindow: Adding WM_STATE fail.\n");
+ }
+
+ #ifdef SHAPE
+
+ /*
+ * Not needed.
+ *
+ * nxagentShapeWindow(pWin);
+ */
+
+ #endif /* SHAPE */
+
+ /*
+ * Mapping of the root window is called by
+ * InitRootWindow in DIX. Skip the operation
+ * if we are in rootless mode.
+ */
+
+ /*
+ * if (!nxagentOption(Rootless) ||
+ * nxagentRootlessWindow != pWin)
+ * {
+ * XMapWindow(nxagentDisplay, nxagentWindow(pWin));
+ * }
+ */
+
+ #ifdef TEST
+ if (nxagentOption(Rootless) && nxagentLastWindowDestroyed)
+ {
+ fprintf(stderr, "nxagentRealizeWindow: Window realized. Stopped termination for rootless session.\n");
+ }
+ #endif
+
+ nxagentAddConfiguredWindow(pWin, CW_Map);
+
+ nxagentLastWindowDestroyed = False;
+
+ return True;
+}
+
+Bool nxagentUnrealizeWindow(pWin)
+ WindowPtr pWin;
+{
+ if (nxagentScreenTrap)
+ {
+ return True;
+ }
+
+ /* add by dimbor */
+ if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
+ {
+ Atom prop = MakeAtom("WM_STATE", strlen("WM_STATE"), True);
+ nxagentWMStateRec wmState;
+ wmState.state = 3; /* WithdrawnState */
+ wmState.icon = None;
+ if (ChangeWindowProperty(pWin, prop, prop, 32, 0, 2, &wmState, 1) != Success)
+ fprintf(stderr, "nxagentUnRealizeWindow: Changing WM_STATE failed.\n");
+ }
+
+ XUnmapWindow(nxagentDisplay, nxagentWindow(pWin));
+
+ return True;
+}
+
+void nxagentFrameBufferPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+
+ void (*PaintWindowBackgroundBackup)(WindowPtr, RegionPtr, int);
+
+ if (pWin->backgroundState == BackgroundPixmap)
+ {
+ pWin->background.pixmap = nxagentVirtualPixmap(pWin->background.pixmap);
+ }
+
+ if (pWin->borderIsPixel == False)
+ {
+ pWin->border.pixmap = nxagentVirtualPixmap(pWin->border.pixmap);
+ }
+
+ PaintWindowBackgroundBackup = pWin->drawable.pScreen -> PaintWindowBackground;
+
+ pWin->drawable.pScreen -> PaintWindowBackground = nxagentFrameBufferPaintWindow;
+
+ fbPaintWindow(pWin, pRegion, what);
+
+ pWin->drawable.pScreen -> PaintWindowBackground = PaintWindowBackgroundBackup;
+
+ if (pWin->backgroundState == BackgroundPixmap)
+ {
+ pWin->background.pixmap = nxagentRealPixmap(pWin->background.pixmap);
+ }
+
+ if (pWin->borderIsPixel == False)
+ {
+ pWin->border.pixmap = nxagentRealPixmap(pWin->border.pixmap);
+ }
+}
+
+void nxagentPaintWindowBackground(pWin, pRegion, what)
+ WindowPtr pWin;
+ RegionPtr pRegion;
+ int what;
+{
+ int i;
+
+ RegionRec temp;
+
+ if (pWin -> realized)
+ {
+ BoxPtr pBox;
+
+ pBox = RegionRects(pRegion);
+
+ for (i = 0; i < RegionNumRects(pRegion); i++)
+ {
+ XClearArea(nxagentDisplay, nxagentWindow(pWin),
+ pBox[i].x1 - pWin->drawable.x,
+ pBox[i].y1 - pWin->drawable.y,
+ pBox[i].x2 - pBox[i].x1,
+ pBox[i].y2 - pBox[i].y1,
+ False);
+ }
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "nxagentPaintWindowBackground: Saving the operation with window "
+ "at [%p] not realized.\n", (void *) pWin);
+ }
+ #endif
+
+ /*
+ * The framebuffer operations don't take care of
+ * clipping to the actual area of the framebuffer
+ * so we need to clip ourselves.
+ */
+
+ RegionInit(&temp, NullBox, 1);
+
+ RegionIntersect(&temp, pRegion, &pWin -> clipList);
+
+ nxagentFrameBufferPaintWindow(pWin, &temp, what);
+
+ RegionUninit(&temp);
+}
+
+void nxagentPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ RegionRec temp;
+
+ /*
+ * The framebuffer operations don't take care of
+ * clipping to the actual area of the framebuffer
+ * so we need to clip ourselves.
+ */
+
+ RegionInit(&temp, NullBox, 1);
+
+ RegionIntersect(&temp, pRegion, &pWin -> borderClip);
+
+ nxagentFrameBufferPaintWindow(pWin, &temp, what);
+
+ RegionUninit(&temp);
+}
+
+void nxagentCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion)
+{
+ fbCopyWindow(pWin, oldOrigin, oldRegion);
+}
+
+void nxagentClipNotify(WindowPtr pWin, int dx, int dy)
+{
+ /*
+ * nxagentConfigureWindow(pWin, CWStackingOrder);
+ */
+
+ nxagentAddConfiguredWindow(pWin, CWStackingOrder);
+ nxagentAddConfiguredWindow(pWin, CW_Shape);
+
+#ifdef NXAGENT_SHAPE
+ return;
+#else
+
+#ifdef SHAPE
+
+/*
+ * nxagentShapeWindow(pWin);
+ */
+
+#endif /* SHAPE */
+
+#endif /* NXAGENT_SHAPE */
+}
+
+void nxagentWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed)
+{
+ /*
+ * The problem: we want to synthetize the expose events internally, so
+ * that we reduce the time between a window operation and the corresp-
+ * onding graphical output, but at the same time we need to take care
+ * of the remote exposures, as we need to handle those cases where our
+ * windows are covered by the windows on the real display. Handling
+ * both the local and the remote exposures we would generate the same
+ * redraws twice, something we call "double refreshes", so we must be
+ * able to identify which events have been already sent to our clients.
+ *
+ * Here is how the algorithm is working:
+ *
+ * - We collect the exposures that the agent sent to its clients in a
+ * region (the "local-region") and store the region for a given win-
+ * dow in a vector.
+ *
+ * - Another region collects the expose that were received from the
+ * real X server (the "remote-region") for the same window.
+ *
+ * - We create a "fake" off-screen window. For every generated region
+ * we send a ConfigureWindow request for that window to synchronize
+ * ourselves with both the remote X server and/or the window manager.
+ *
+ * - When the ConfigureNotify is received, we calculate the difference
+ * between the "remote-region" and the "local-region" for the window
+ * that had collected exposures.
+ *
+ * - Finally we send the resulting exposures to our clients.
+ *
+ * As you may have guessed, the windows are synchronized per-region,
+ * that is there is a single region for a set of exposures. The regions
+ * are handled in order. This means that we can always calculate the
+ * final region by referring to the first element of the vector.
+ */
+
+ RegionRec temp;
+ BoxRec box;
+
+ if (nxagentSessionState != SESSION_DOWN)
+ {
+ if (nxagentExposeArrayIsInitialized == 0)
+ {
+ int i;
+
+ XSetWindowAttributes attributes;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowExposures: Initializing expose queue.\n");
+ #endif
+
+ attributes.event_mask = StructureNotifyMask;
+
+ for (i = 0; i < EXPOSED_SIZE; i++)
+ {
+ nxagentExposeQueue.exposures[i].pWindow = NULL;
+ nxagentExposeQueue.exposures[i].localRegion = NullRegion;
+ nxagentExposeQueue.exposures[i].remoteRegion = NullRegion;
+ nxagentExposeQueue.exposures[i].remoteRegionIsCompleted = False;
+ nxagentExposeQueue.exposures[i].serial = 0;
+ }
+
+ nxagentExposeQueue.length = 0;
+
+ nxagentExposeSerial = 0;
+
+ nxagentExposeQueue.start = 0;
+
+ nxagentConfiguredSynchroWindow = XCreateWindow(nxagentDisplay, DefaultRootWindow(nxagentDisplay), 0, 0,
+ 1, 1, 0, 0, InputOutput, 0, CWEventMask, &attributes);
+
+ nxagentInitRemoteExposeRegion();
+
+ nxagentExposeArrayIsInitialized = 1;
+ }
+
+ RegionInit(&temp, (BoxRec *) NULL, 1);
+
+ if (pRgn != NULL)
+ {
+ if (RegionNumRects(pRgn) > RECTLIMIT)
+ {
+ box = *RegionExtents(pRgn);
+
+ RegionEmpty(pRgn);
+ RegionInit(pRgn, &box, 1);
+ }
+
+ RegionUnion(&temp, &temp, pRgn);
+ }
+
+ if (other_exposed != NULL)
+ {
+ RegionUnion(&temp, &temp, other_exposed);
+ }
+
+ if (RegionNil(&temp) == 0)
+ {
+ RegionTranslate(&temp,
+ -(pWin -> drawable.x), -(pWin -> drawable.y));
+
+ if (nxagentExposeQueue.length < EXPOSED_SIZE)
+ {
+ int index;
+
+ index = (nxagentExposeQueue.start + nxagentExposeQueue.length) % EXPOSED_SIZE;
+
+ nxagentExposeQueue.exposures[index].pWindow = pWin;
+
+ nxagentExposeQueue.exposures[index].localRegion = RegionCreate(NULL, 1);
+
+ if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) &&
+ (nxagentWindowPriv(pWin) -> isMapped == 0 ||
+ nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured))
+ {
+ nxagentExposeQueue.exposures[index].remoteRegion = RegionCreate(NULL, 1);
+
+ RegionUnion(nxagentExposeQueue.exposures[index].remoteRegion,
+ nxagentExposeQueue.exposures[index].remoteRegion, &temp);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowExposures: Added region to remoteRegion for window [%ld] to position [%d].\n",
+ nxagentWindow(pWin), nxagentExposeQueue.length);
+ #endif
+ }
+ else
+ {
+ RegionUnion(nxagentExposeQueue.exposures[index].localRegion,
+ nxagentExposeQueue.exposures[index].localRegion, &temp);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowExposures: Added region to localRegion for window [%ld] to position [%d].\n",
+ nxagentWindow(pWin), nxagentExposeQueue.length);
+ #endif
+ }
+
+ nxagentExposeSerial = (nxagentExposeSerial - 1) % EXPOSED_SIZE;
+
+ nxagentExposeQueue.exposures[index].serial = nxagentExposeSerial;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowExposures: Added region to queue with serial [%d].\n", nxagentExposeSerial);
+ #endif
+
+ /*
+ * Mark this region for sending a synchro,
+ * in nxagentFlushConfigureWindow().
+ */
+
+ nxagentExposeQueue.exposures[index].synchronize = 1;
+
+ nxagentExposeQueue.length++;
+
+ if (nxagentOption(Rootless) && nxagentWindowPriv(pWin) &&
+ (nxagentWindowPriv(pWin) -> isMapped == 0 ||
+ nxagentWindowPriv(pWin) -> visibilityState != VisibilityUnobscured))
+ {
+ RegionUninit(&temp);
+
+ return;
+ }
+ }
+ else
+ {
+ RegionUninit(&temp);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentWindowExposures: WARNING! Reached maximum size of collect exposures vector.\n");
+ #endif
+
+ if ((pRgn != NULL && RegionNotEmpty(pRgn) != 0) ||
+ (other_exposed != NULL && RegionNotEmpty(other_exposed) != 0))
+ {
+ nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed);
+
+ miWindowExposures(pWin, pRgn, other_exposed);
+ }
+
+ return;
+ }
+ }
+
+ RegionUninit(&temp);
+ }
+
+ if ((pRgn != NULL && RegionNotEmpty(pRgn) != 0) ||
+ (other_exposed != NULL && RegionNotEmpty(other_exposed) != 0))
+ {
+ nxagentUnmarkExposedRegion(pWin, pRgn, other_exposed);
+
+ miWindowExposures(pWin, pRgn, other_exposed);
+ }
+
+ return;
+}
+
+#ifdef SHAPE
+static Bool nxagentRegionEqual(RegionPtr pReg1, RegionPtr pReg2)
+{
+ BoxPtr pBox1, pBox2;
+ unsigned int n1, n2;
+
+ if (pReg1 == pReg2) return True;
+
+ if (pReg1 == NullRegion || pReg2 == NullRegion) return False;
+
+ pBox1 = RegionRects(pReg1);
+ n1 = RegionNumRects(pReg1);
+
+ pBox2 = RegionRects(pReg2);
+ n2 = RegionNumRects(pReg2);
+
+ if (n1 != n2) return False;
+
+ if (pBox1 == pBox2) return True;
+
+ if (memcmp(pBox1, pBox2, n1 * sizeof(BoxRec))) return False;
+
+ return True;
+}
+
+void nxagentShapeWindow(WindowPtr pWin)
+{
+ Region reg;
+ BoxPtr pBox;
+ XRectangle rect;
+ int i;
+
+ if (NXDisplayError(nxagentDisplay) == 1)
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: Window at [%p][%ld].\n",
+ (void *) pWin, nxagentWindow(pWin));
+ #endif
+
+ if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->boundingShape,
+ wBoundingShape(pWin)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: Bounding shape differs.\n");
+ #endif
+
+ if (wBoundingShape(pWin))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: wBounding shape has [%ld] rects.\n",
+ RegionNumRects(wBoundingShape(pWin)));
+ #endif
+
+#ifdef NXAGENT_SHAPE2
+ if (!nxagentWindowPriv(pWin)->boundingShape)
+ {
+ nxagentWindowPriv(pWin)->boundingShape = RegionCreate(NULL, 1);
+ }
+#endif
+
+ RegionCopy(
+ nxagentWindowPriv(pWin)->boundingShape, wBoundingShape(pWin));
+
+ reg = XCreateRegion();
+ pBox = RegionRects(nxagentWindowPriv(pWin)->boundingShape);
+ for (i = 0;
+ i < RegionNumRects(nxagentWindowPriv(pWin)->boundingShape);
+ i++)
+ {
+ rect.x = pBox[i].x1;
+ rect.y = pBox[i].y1;
+ rect.width = pBox[i].x2 - pBox[i].x1;
+ rect.height = pBox[i].y2 - pBox[i].y1;
+ XUnionRectWithRegion(&rect, reg, reg);
+ }
+
+#ifndef NXAGENT_SHAPE
+ XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin),
+ ShapeBounding, 0, 0, reg, ShapeSet);
+#endif
+
+ XDestroyRegion(reg);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: wBounding shape does not exist. Removing the shape.\n");
+ #endif
+
+ RegionEmpty(
+ nxagentWindowPriv(pWin)->boundingShape);
+
+#ifndef NXAGENT_SHAPE
+ XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin),
+ ShapeBounding, 0, 0, None, ShapeSet);
+#endif
+
+ }
+ }
+
+ if (!nxagentRegionEqual(nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: Clip shape differs.\n");
+ #endif
+
+ if (wClipShape(pWin))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: wClip shape has [%ld] rects.\n",
+ RegionNumRects(wClipShape(pWin)));
+ #endif
+
+#ifdef NXAGENT_SHAPE2
+ if (!nxagentWindowPriv(pWin)->clipShape)
+ {
+ nxagentWindowPriv(pWin)->clipShape = RegionCreate(NULL, 1);
+ }
+#endif
+
+ RegionCopy(
+ nxagentWindowPriv(pWin)->clipShape, wClipShape(pWin));
+
+ reg = XCreateRegion();
+ pBox = RegionRects(nxagentWindowPriv(pWin)->clipShape);
+ for (i = 0;
+ i < RegionNumRects(nxagentWindowPriv(pWin)->clipShape);
+ i++)
+ {
+ rect.x = pBox[i].x1;
+ rect.y = pBox[i].y1;
+ rect.width = pBox[i].x2 - pBox[i].x1;
+ rect.height = pBox[i].y2 - pBox[i].y1;
+ XUnionRectWithRegion(&rect, reg, reg);
+ }
+
+#ifndef NXAGENT_SHAPE
+ XShapeCombineRegion(nxagentDisplay, nxagentWindow(pWin),
+ ShapeClip, 0, 0, reg, ShapeSet);
+#endif
+
+ XDestroyRegion(reg);
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentShapeWindow: wClip shape does not exist. Removing the shape.\n");
+ #endif
+
+ RegionEmpty(
+ nxagentWindowPriv(pWin)->clipShape);
+
+#ifndef NXAGENT_SHAPE
+ XShapeCombineMask(nxagentDisplay, nxagentWindow(pWin),
+ ShapeClip, 0, 0, None, ShapeSet);
+#endif
+ }
+ }
+}
+#endif /* SHAPE */
+
+static int nxagentForceExposure(WindowPtr pWin, void * ptr)
+{
+ RegionPtr exposedRgn;
+ BoxRec Box;
+ WindowPtr pRoot = pWin->drawable.pScreen->root;
+
+ if (pWin -> drawable.class != InputOnly)
+ {
+ Box.x1 = pWin->drawable.x;
+ Box.y1 = pWin->drawable.y;
+ Box.x2 = Box.x1 + pWin->drawable.width;
+ Box.y2 = Box.y1 + pWin->drawable.height;
+
+ exposedRgn = RegionCreate(&Box, 1);
+ RegionIntersect(exposedRgn, exposedRgn, &pRoot->winSize);
+
+ if (exposedRgn != NULL && RegionNotEmpty(exposedRgn) != 0)
+ {
+ miWindowExposures(pWin, exposedRgn, NullRegion);
+ }
+
+ RegionDestroy(exposedRgn);
+ }
+
+ return WT_WALKCHILDREN;
+}
+
+void nxagentRefreshWindows(WindowPtr pWin)
+{
+ int action = 1;
+
+ TraverseTree(pWin, nxagentForceExposure, &action);
+}
+
+void nxagentUnmapWindows(void)
+{
+ int i;
+
+ if (nxagentOption(Fullscreen) == 1)
+ {
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (nxagentDefaultWindows[i])
+ {
+ XUnmapWindow(nxagentDisplay, nxagentDefaultWindows[i]);
+ }
+ }
+ }
+
+ NXFlushDisplay(nxagentDisplay, NXFlushLink);
+}
+
+void nxagentMapDefaultWindows()
+{
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ WindowPtr pWin = screenInfo.screens[i]->root;
+
+ ScreenPtr pScreen = pWin -> drawable.pScreen;
+
+ MapWindow(pWin, serverClient);
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ /*
+ * Show the NX splash screen.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentMapDefaultWindows: Showing the splash window.\n");
+ #endif
+
+ nxagentShowSplashWindow(nxagentDefaultWindows[pScreen->myNum]);
+
+ /*
+ * Map the default window. Defer the mapping if the session is
+ * of shadow type. If no WM is running on the remote display,
+ * map the window soon anyway: this avoids a flickering effect
+ * on the !M logo if the shadow session is displayed from a
+ * Windows client.
+ */
+
+ if (nxagentOption(Shadow) == 0 || nxagentWMIsRunning == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMapDefaultWindows: Mapping default window id [%ld].\n",
+ nxagentDefaultWindows[pScreen->myNum]);
+ #endif
+
+ XMapWindow(nxagentDisplay, nxagentDefaultWindows[pScreen->myNum]);
+
+ if (nxagentOption(Fullscreen) == 1 && nxagentWMIsRunning == 1)
+ {
+ nxagentMaximizeToFullScreen(pScreen);
+ }
+ }
+
+ /*
+ * Map and raise the input window.
+ */
+
+ XMapWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]);
+
+ /*
+ * At reconnection the Input Window is
+ * raised in nxagentReconnectAllWindows,
+ * after the Root Window is mapped.
+ */
+
+ if (nxagentReconnectTrap == 0)
+ {
+ XRaiseWindow(nxagentDisplay, nxagentInputWindows[pScreen->myNum]);
+ }
+ }
+
+ /*
+ * Send a SetSelectionOwner request
+ * to notify of the agent start.
+ */
+
+ XSetSelectionOwner(nxagentDisplay, serverCutProperty,
+ nxagentDefaultWindows[i], CurrentTime);
+ }
+
+ /*
+ * Map the icon window.
+ */
+
+ if (nxagentIconWindow != 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentMapDefaultWindows: Mapping icon window id [%ld].\n",
+ nxagentIconWindow);
+ #endif
+
+ XMapWindow(nxagentDisplay, nxagentIconWindow);
+
+ if (nxagentIpaq != 0)
+ {
+ XIconifyWindow(nxagentDisplay, nxagentIconWindow,
+ DefaultScreen(nxagentDisplay));
+ }
+ }
+
+ /*
+ * Ensure that the fullscreen window gets the focus.
+ */
+
+ if (nxagentFullscreenWindow != 0)
+ {
+ XSetInputFocus(nxagentDisplay, nxagentFullscreenWindow,
+ RevertToParent, CurrentTime);
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentMapDefaultWindows: Completed mapping of default windows.\n");
+ #endif
+}
+
+Bool nxagentDisconnectAllWindows(void)
+{
+ Bool succeded = True;
+ int i;
+ WindowPtr pWin;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
+ fprintf(stderr, "nxagentDisconnectAllWindows\n");
+ #endif
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pWin = screenInfo.screens[i]->root;
+ nxagentTraverseWindow( pWin, nxagentDisconnectWindow, &succeded);
+ nxagentDefaultWindows[i] = None;
+ }
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+ fprintf(stderr, "nxagentDisconnectAllWindows: all windows disconnected\n");
+ #endif
+
+ return succeded;
+}
+
+/*
+ * FIXME: We are giving up reconnecting those void *
+ * that are not resource, and we are just disconnecting them.
+ * perhaps we could do better and reconnect them.
+ */
+
+void nxagentDisconnectWindow(void * p0, XID x1, void * p2)
+{
+ WindowPtr pWin = (WindowPtr)p0;
+ Bool* pBool = (Bool*)p2;
+ CursorPtr pCursor = wCursor(pWin);
+ ScreenPtr pScreen = pWin -> drawable.pScreen;
+
+ if ((pCursor = wCursor(pWin)) &&
+ nxagentCursorPriv(pCursor, pScreen) &&
+ nxagentCursor(pCursor, pScreen))
+ {
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG_disabled
+ char msg[] = "nxagentDisconnectWindow:";
+
+ nxagentPrintCursorInfo(pCursor, msg);
+ #endif
+
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ fprintf(stderr, "nxagentDisconnectWindow: window %p - disconnecting cursor %p ID %lx\n",
+ pWin, pCursor, nxagentCursor(pCursor, pScreen));
+ #endif
+
+ nxagentDisconnectCursor(pCursor, (XID)0, pBool);
+
+ if (*pBool == False)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentDisconnectWindow: WARNING failed disconnection of cursor at [%p]"
+ " for window at [%p]: ignoring it.\n", (void*)pCursor, (void*)pWin);
+ #endif
+
+ *pBool = True;
+ }
+ }
+ #ifdef NXAGENT_RECONNECT_CURSOR_DEBUG
+ else if (pCursor)
+ {
+ fprintf(stderr, "nxagentDisconnectWindow: window %p - cursor %p already disconnected\n",
+ pWin, pCursor);
+ }
+ #endif
+
+ nxagentWindow(pWin) = None;
+
+ if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
+ {
+ nxagentDestroyCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
+ }
+}
+
+Bool nxagentReconnectAllWindows(void *p0)
+{
+ int flexibility = *(int *) p0;
+
+ flexibility = flexibility;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
+ fprintf(stderr, "nxagentReconnectAllWindows\n");
+ #endif
+
+ if (screenInfo.screens[0]->root -> backgroundState == BackgroundPixmap &&
+ screenInfo.screens[0]->root -> background.pixmap == NULL)
+ {
+ FatalError("nxagentReconnectAllWindows: correct the FIXME\n");
+ }
+
+ if (nxagentOption(Fullscreen))
+ {
+ screenInfo.screens[0]->root -> origin.x = nxagentOption(RootX);
+ screenInfo.screens[0]->root -> origin.y = nxagentOption(RootY);
+ }
+
+ if (!nxagentLoopOverWindows(nxagentReconnectWindow))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectAllWindows: couldn't recreate windows\n");
+ #endif
+
+ return False;
+ }
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+ XSync(nxagentDisplay, 0);
+ fprintf(stderr, "nxagentReconnectAllWindows: all windows recreated\n");
+ #endif
+
+ if (!nxagentLoopOverWindows(nxagentReconfigureWindow))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectAllWindows: couldn't reconfigure windows\n");
+ #endif
+
+ return False;
+ }
+
+ /*
+ * After the Root Window has
+ * been mapped, the Input
+ * Windows is raised.
+ */
+
+ if (nxagentOption(Rootless) == 0)
+ {
+ int i;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ XRaiseWindow(nxagentDisplay, nxagentInputWindows[i]);
+ }
+ }
+
+ nxagentFlushConfigureWindow();
+
+ if (nxagentOption(Fullscreen))
+ {
+ screenInfo.screens[0]->root -> origin.x = 0;
+ screenInfo.screens[0]->root -> origin.y = 0;
+ }
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ fprintf(stderr, "nxagentReconnectAllWindows: All windows reconfigured.\n");
+
+ #endif
+
+ if (nxagentInitClipboard(screenInfo.screens[0]->root) == -1)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectAllWindows: WARNING! Couldn't initialize the clipboard.\n");
+ #endif
+
+ return False;
+ }
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+
+ XSync(nxagentDisplay, 0);
+
+ fprintf(stderr, "nxagentReconnectAllWindows: Clipboard initialized.\n");
+
+ #endif
+
+ #ifdef VIEWPORT_FRAME
+
+ /*
+ * We move the viewport frames out of the way on the X server side.
+ */
+
+ if (nxagentViewportFrameLeft &&
+ nxagentViewportFrameRight &&
+ nxagentViewportFrameAbove &&
+ nxagentViewportFrameBelow)
+ {
+ XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameLeft),
+ -NXAGENT_FRAME_WIDTH, 0);
+ XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameRight),
+ nxagentOption(RootWidth), 0);
+ XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameAbove),
+ 0, -NXAGENT_FRAME_WIDTH);
+ XMoveWindow(nxagentDisplay, nxagentWindow(nxagentViewportFrameBelow),
+ 0, nxagentOption(RootHeight));
+ }
+
+ #endif /* #ifdef VIEWPORT_FRAME */
+
+ return True;
+}
+
+Bool nxagentSetWindowCursors(void *p0)
+{
+ int flexibility = *(int *) p0;
+
+ flexibility = flexibility;
+
+ #if defined(NXAGENT_RECONNECT_DEBUG) || defined(NXAGENT_RECONNECT_WINDOW_DEBUG)
+ fprintf(stderr, "nxagentSetWindowCursors: Going to loop over the windows.\n");
+ #endif
+
+ if (!nxagentLoopOverWindows(nxagentReconfigureWindowCursor))
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentSetWindowCursors: WARNING! Couldn't configure all windows' cursors.\n");
+ #endif
+
+ return False;
+ }
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+ fprintf(stderr, "nxagentLoopOverWindows: All cursors configured.\n");
+ #endif
+
+ nxagentReDisplayCurrentCursor();
+
+ return True;
+}
+
+static void nxagentTraverseWindow(
+ WindowPtr pWin,
+ void (*pF)(void *, XID, void *),
+ void * p)
+{
+ pF(pWin, 0, p);
+
+ if (pWin -> nextSib)
+ {
+ nxagentTraverseWindow(pWin -> nextSib, pF, p);
+ }
+
+ if (pWin -> firstChild)
+ {
+ nxagentTraverseWindow(pWin -> firstChild, pF, p);
+ }
+}
+
+static Bool nxagentLoopOverWindows(void (*pF)(void *, XID, void *))
+{
+ int i;
+ Bool windowSuccess = True;
+ WindowPtr pWin;
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pWin = screenInfo.screens[i]->root;
+ nxagentTraverseWindow(pWin, pF, &windowSuccess);
+ }
+
+ return windowSuccess;
+}
+
+static void nxagentReconnectWindow(void * param0, XID param1, void * data_buffer)
+{
+ WindowPtr pWin = (WindowPtr)param0;
+ Bool *pBool = (Bool*)data_buffer;
+ Visual *visual;
+ unsigned long mask;
+ XSetWindowAttributes attributes;
+ ColormapPtr pCmap;
+
+ if (!pWin || !*pBool)
+ return;
+
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+ fprintf(stderr, "nxagentReconnectWindow: %p - ID %lx\n", pWin, nxagentWindow(pWin));
+ #endif
+
+ if (pWin->drawable.class == InputOnly) {
+ mask = CWEventMask;
+ visual = CopyFromParent;
+ }
+ else {
+ mask = CWEventMask | CWBackingStore;
+
+ attributes.backing_store = NotUseful;
+
+ if (pWin->optional)
+ {
+ mask |= CWBackingPlanes | CWBackingPixel;
+ attributes.backing_planes = pWin->optional->backingBitPlanes;
+ attributes.backing_pixel = pWin->optional->backingPixel;
+ }
+
+/*
+FIXME: Do we need to set save unders attribute here?
+*/
+ if (nxagentSaveUnder == True)
+ {
+ mask |= CWSaveUnder;
+ attributes.save_under = pWin->saveUnder;
+ }
+
+ if (pWin->parent) {
+ if (pWin->optional && pWin->optional->visual != wVisual(pWin->parent)) {
+ visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
+ mask |= CWColormap;
+ if (pWin->optional->colormap) {
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
+ attributes.colormap = nxagentColormap(pCmap);
+ }
+ else
+ attributes.colormap = nxagentDefaultVisualColormap(visual);
+ }
+ else
+ visual = CopyFromParent;
+ }
+ else { /* root windows have their own colormaps at creation time */
+ visual = nxagentVisualFromID(pWin->drawable.pScreen, wVisual(pWin));
+ pCmap = (ColormapPtr)LookupIDByType(wColormap(pWin), RT_COLORMAP);
+ mask |= CWColormap;
+ attributes.colormap = nxagentColormap(pCmap);
+ }
+ }
+
+ if (mask & CWEventMask)
+ {
+ /* Assume that the mask fits in int... broken on Big Endian 64bit systems. */
+ Mask tmp_mask = attributes.event_mask;
+ nxagentGetEventMask(pWin, &tmp_mask);
+ attributes.event_mask = (int)tmp_mask;
+ }
+ #ifdef WARNING
+ else
+ {
+ attributes.event_mask = NoEventMask;
+ }
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectWindow: Going to create new window.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectWindow: Recreating %swindow at %p current event mask = %lX mask & CWEventMask = %ld "
+ "event_mask = %lX\n",
+ nxagentWindowTopLevel(pWin) ? "toplevel " : "", (void*)pWin, pWin -> eventMask,
+ mask & CWEventMask, attributes.event_mask);
+ #endif
+
+ /*
+ * FIXME: This quick hack is intended to solve a
+ * problem of NXWin X server for windows.
+ * The NXWin minimize the windows moving them
+ * out of the screen area, this behaviour
+ * can cause problem when a rootless session
+ * is disconnected and an apps is minimized.
+ * It will be solved with new Xorg version of
+ * the NXWin server.
+ */
+
+ if (nxagentOption(Rootless))
+ {
+ if (pWin -> drawable.x == -32000 && pWin -> drawable.y == -32000)
+ {
+ pWin -> drawable.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2;
+ pWin -> drawable.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) /2;
+ }
+
+ if (pWin -> origin.x == -32000 && pWin -> origin.y == -32000)
+ {
+ pWin -> origin.x = (pWin -> drawable.pScreen -> width - pWin -> drawable.width) / 2;
+ pWin -> origin.y = (pWin -> drawable.pScreen -> height - pWin -> drawable.height) / 2;
+ }
+ }
+
+ nxagentWindow(pWin) = XCreateWindow(nxagentDisplay,
+ nxagentWindowParent(pWin),
+ pWin->origin.x -
+ wBorderWidth(pWin),
+ pWin->origin.y -
+ wBorderWidth(pWin),
+ pWin->drawable.width,
+ pWin->drawable.height,
+ pWin->borderWidth,
+ pWin->drawable.depth,
+ pWin->drawable.class,
+ visual,
+ mask,
+ &attributes);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectWindow: Created new window with id [%ld].\n",
+ nxagentWindowPriv(pWin)->window);
+ #endif
+
+ /*
+ * We have to set the WM_DELETE_WINDOW protocols
+ * on every top level window, because we don't know
+ * if a client handles this.
+ */
+
+ if (nxagentOption(Rootless) && (pWin != screenInfo.screens[0]->root))
+ {
+ if (nxagentWindowTopLevel(pWin))
+ {
+ Atom prop = nxagentMakeAtom("WM_PROTOCOLS", strlen("WM_PROTOCOLS"), True);
+
+ XlibAtom atom = nxagentMakeAtom("WM_DELETE_WINDOW", strlen("WM_DELETE_WINDOW"), True);
+
+ XSetWMProtocols(nxagentDisplay, nxagentWindow(pWin), &atom, 1);
+
+ nxagentAddPropertyToList(prop, pWin);
+ }
+
+ nxagentExportAllProperty(pWin);
+
+ if (nxagentWindowTopLevel(pWin))
+ {
+ int ret;
+ Atom type;
+ int format;
+ unsigned long nItems, bytesLeft;
+ XSizeHints *props, hints;
+ unsigned char *data = NULL;
+
+ #ifdef _XSERVER64
+
+ unsigned char *data64 = NULL;
+ unsigned int i;
+
+ #endif
+
+ hints.flags = 0;
+
+ ret = GetWindowProperty(pWin,
+ XA_WM_NORMAL_HINTS,
+ 0, sizeof(XSizeHints),
+ False, XA_WM_SIZE_HINTS,
+ &type, &format, &nItems, &bytesLeft, &data);
+
+ /*
+ * 72 is the number of bytes returned by
+ * sizeof(XSizeHints) on 32 bit platforms.
+ */
+
+ if (ret == Success &&
+ ((format >> 3) * nItems) == 72 &&
+ bytesLeft == 0 &&
+ type == XA_WM_SIZE_HINTS)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentReconnectWindow: setting WMSizeHints on window %p [%lx - %lx].\n",
+ (void*)pWin, pWin -> drawable.id, nxagentWindow(pWin));
+ #endif
+
+ #ifdef _XSERVER64
+
+ data64 = (unsigned char *) malloc(sizeof(XSizeHints) + 4);
+
+ for (i = 0; i < 4; i++)
+ {
+ *(data64 + i) = *(data + i);
+ }
+
+ *(((int *) data64) + 1) = 0;
+
+ for (i = 8; i < sizeof(XSizeHints) + 4; i++)
+ {
+ *(data64 + i) = *(data + i - 4);
+ }
+
+ props = (XSizeHints *) data64;
+
+ #else
+
+ props = (XSizeHints *) data;
+
+ #endif /* _XSERVER64 */
+
+ hints = *props;
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconnectWindow: Failed to get property WM_NORMAL_HINTS on window %p\n",
+ (void*)pWin);
+ #endif
+ }
+
+ hints.flags |= (USPosition | PWinGravity);
+ hints.x = pWin -> drawable.x;
+ hints.y = pWin -> drawable.y;
+ hints.win_gravity = StaticGravity;
+
+ XSetWMNormalHints(nxagentDisplay,
+ nxagentWindow(pWin),
+ &hints);
+
+ #ifdef _XSERVER64
+
+ if (data64 != NULL)
+ {
+ free(data64);
+ }
+
+ #endif
+ }
+ }
+
+ if (nxagentDrawableStatus((DrawablePtr) pWin) == NotSynchronized)
+ {
+ nxagentAllocateCorruptedResource((DrawablePtr) pWin, RT_NX_CORR_WINDOW);
+ }
+}
+
+static void nxagentReconfigureWindowCursor(void * param0, XID param1, void * data_buffer)
+{
+ WindowPtr pWin = (WindowPtr)param0;
+ Bool *pBool = (Bool*)data_buffer;
+ CursorPtr pCursor;
+ ScreenPtr pScreen;
+
+ if (!pWin || !*pBool || !(pCursor = wCursor(pWin)))
+ return;
+
+ pScreen = pWin -> drawable.pScreen;
+
+ if (!(nxagentCursorPriv(pCursor, pScreen)))
+ {
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconfigureWindowCursor: %p - ID %lx geometry (%d,%d,%d,%d) "
+ "cursor %p - ID %lx\n",
+ pWin, nxagentWindow(pWin),
+ pWin -> drawable.x,
+ pWin -> drawable.y,
+ pWin -> drawable.width,
+ pWin -> drawable.height,
+ pCursor, nxagentCursor(pCursor, pScreen));
+ #endif
+
+ if (nxagentCursor(pCursor, pScreen) == None)
+ {
+ #ifdef NXAGENT_RECONNECT_WINDOW_DEBUG
+ fprintf(stderr, "nxagentReconfigureWindowCursor: reconnecting valid cursor %lx\n",
+ (void*)pCursor);
+ #endif
+
+ nxagentReconnectCursor(pCursor, 0, pBool);
+
+ if (!*pBool)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentReconfigureWindowCursor: WARNING "
+ "failed reconnection of cursor at [%p] for window at [%p]: ignoring it.\n",
+ (void*)pCursor, (void*)pWin);
+ #endif
+
+ *pBool = True;
+ }
+ }
+
+ if (nxagentOption(Rootless))
+ {
+ XDefineCursor(nxagentDisplay,nxagentWindow(pWin),nxagentCursor(pCursor,pScreen));
+ }
+}
+
+static void nxagentReconfigureWindow(void * param0, XID param1, void * data_buffer)
+{
+ WindowPtr pWin = (WindowPtr)param0;
+ unsigned long mask = 0;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentReconfigureWindow: pWin %p - ID %lx\n", pWin, nxagentWindow(pWin));
+ #endif
+
+ if (pWin -> drawable.class == InputOnly)
+ mask = CWWinGravity | CWEventMask | CWDontPropagate | CWOverrideRedirect | CWCursor;
+ else
+ mask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBorderPixel |
+ CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPlanes |
+ CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask |
+ CWDontPropagate | CWColormap | CWCursor;
+
+ nxagentChangeWindowAttributes(pWin, mask);
+
+#ifdef SHAPE
+ if (nxagentWindowPriv(pWin) -> boundingShape)
+ {
+ RegionDestroy(
+ nxagentWindowPriv(pWin) -> boundingShape);
+ nxagentWindowPriv(pWin) -> boundingShape = NULL;
+ }
+
+ if (nxagentWindowPriv(pWin) -> clipShape)
+ {
+ RegionDestroy(
+ nxagentWindowPriv(pWin) -> clipShape);
+ nxagentWindowPriv(pWin) -> clipShape = NULL;
+ }
+ nxagentShapeWindow(pWin);
+#endif
+
+ if (pWin != screenInfo.screens[0]->root)
+ {
+ if (pWin->realized)
+ {
+ nxagentRealizeWindow (pWin);
+ }
+/*
+XXX: This would break Motif menus.
+ If pWin is mapped but not realized, a followin UnmapWindow() wouldn't
+ do anything, leaving this mapped window around. XMapWindow()
+ is called in nxagentRealizeWindow() and there it is enough.
+
+ else if (pWin->mapped)
+ {
+ XMapWindow(nxagentDisplay, nxagentWindow(pWin));
+ }
+*/
+ else if (nxagentOption(Rootless) && pWin -> overrideRedirect == 0 &&
+ nxagentWindowTopLevel(pWin) && nxagentIsIconic(pWin))
+ {
+ MapWindow(pWin, serverClient);
+ XIconifyWindow(nxagentDisplay, nxagentWindow(pWin), pWin -> drawable.pScreen -> myNum);
+ }
+ }
+ else if (nxagentOption(Rootless) == 0)
+ {
+ /*
+ * Map the root window.
+ */
+
+ XMoveWindow(nxagentDisplay, nxagentWindow(pWin),
+ nxagentOption(RootX), nxagentOption(RootY));
+
+ XMapWindow(nxagentDisplay, nxagentWindow(pWin));
+ }
+}
+
+Bool nxagentCheckIllegalRootMonitoring(WindowPtr pWin, Mask mask)
+{
+ Mask invalidMask = SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask;
+
+ if (nxagentOption(Rootless) &&
+ pWin == screenInfo.screens[0]->root &&
+ (mask & invalidMask))
+ {
+ return True;
+ }
+
+ return False;
+}
+
+#ifdef TEST
+
+Bool nxagentCheckWindowIntegrity(WindowPtr pWin)
+{
+ Bool integrity = True;
+ XImage *image;
+ char *data;
+ int format;
+ unsigned long plane_mask = AllPlanes;
+ unsigned int width, height, length, depth;
+
+ width = pWin -> drawable.width;
+ height = pWin -> drawable.height;
+ depth = pWin -> drawable.depth;
+ format = (depth == 1) ? XYPixmap : ZPixmap;
+
+ if (width && height)
+ {
+ length = nxagentImageLength(width, height, format, 0, depth);
+ data = malloc(length);
+
+ if (data == NULL)
+ {
+ FatalError("nxagentCheckWindowIntegrity: Failed to allocate a buffer of size %d.\n", length);
+ }
+
+ memset(data, 0, length);
+
+ image = XGetImage(nxagentDisplay, nxagentWindow(pWin), 0, 0,
+ width, height, plane_mask, format);
+ if (image == NULL)
+ {
+ fprintf(stderr, "XGetImage: Failed.\n");
+ return False;
+ }
+
+ fbGetImage((DrawablePtr)pWin, 0, 0, width, height, format, plane_mask, data);
+
+ if (image && memcmp(image->data, data, length) != 0)
+ {
+ #ifdef TEST
+ int i;
+ char *p, *q;
+ #endif
+
+ integrity = False;
+
+ #ifdef TEST
+ for (i = 0, p = image->data, q = data; i < length; i++)
+ {
+ if (p[i] != q[i])
+ {
+ fprintf(stderr, "[%d] %d - %d !!!!!!!!!!!!!!!!!!! **************** !!!!!!!!!!!!!!!!!\n", i, p[i], q[i]);
+ }
+ else
+ {
+ fprintf(stderr, "[%d] %d - %d\n", i, p[i], q[i]);
+ }
+ }
+ #endif
+
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p width %d, height %d, has been realized "
+ "but the data buffer still differs.\n", (void*) pWin, width, height);
+ fprintf(stderr, "nxagentCheckWindowIntegrity: bytes_per_line = %d byte pad %d format %d.\n",
+ image -> bytes_per_line, nxagentImagePad(width, height, 0, depth), image->format);
+
+ fprintf(stderr, "nxagentCheckWindowIntegrity: image is corrupted!!\n");
+ #endif
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckWindowIntegrity: Window %p has been realized "
+ "now remote and frambuffer data are synchronized.\n", (void*) pWin);
+ #endif
+ }
+
+ if (image)
+ {
+ XDestroyImage(image);
+ }
+
+ if (data)
+ {
+ free(data);
+ }
+ }
+ else
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentCheckWindowIntegrity: ignored window %p with geometry (%d,%d).\n",
+ (void*) pWin, width, height);
+ #endif
+ }
+
+ return integrity;
+}
+
+#endif
+
+Bool nxagentIsIconic(WindowPtr pWin)
+{
+ int iReturn;
+ unsigned long ulReturnItems;
+ unsigned long ulReturnBytesLeft;
+ Atom atomReturnType;
+ int iReturnFormat;
+ unsigned char *pszReturnData = NULL;
+
+ if (!wUserProps (pWin))
+ {
+ return 0;
+ }
+
+ iReturn = GetWindowProperty(pWin, MakeAtom("WM_STATE", 8, False), 0, sizeof(CARD32), False,
+ AnyPropertyType, &atomReturnType, &iReturnFormat,
+ &ulReturnItems, &ulReturnBytesLeft, &pszReturnData);
+
+ if (iReturn == Success)
+ {
+ return (((CARD32 *)pszReturnData)[0] == IconicState);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void nxagentSetTopLevelEventMask(pWin)
+ WindowPtr pWin;
+{
+ unsigned long mask = CWEventMask;
+ XSetWindowAttributes attributes;
+
+ if (nxagentOption(Rootless) && nxagentWindowTopLevel(pWin))
+ {
+ /* Assume that the mask fits in int... broken on Big Endian 64bit systems. */
+ Mask tmp_mask = attributes.event_mask = NoEventMask;
+ nxagentGetEventMask(pWin, &tmp_mask);
+ attributes.event_mask = (int)tmp_mask;
+
+ XChangeWindowAttributes(nxagentDisplay, nxagentWindow(pWin), mask, &attributes);
+ }
+}
+
+/*
+ * This function must return 1 if we want the
+ * exposures to be sent as the window's extents.
+ * This is actually a harmless, but useful hack,
+ * as it speeds up the window redraws considera-
+ * bly, when using a very popular WM theme.
+ */
+
+int nxagentExtentsPredicate(int total)
+{
+ #ifdef TEST
+
+ if (total == 6 || total == 11 || total == 10)
+ {
+ fprintf(stderr, "nxagentExtentsPredicate: WARNING! Returning [%d] with [%d] rectangles.\n",
+ (total == 6 || total == 11 || total == 10), total);
+ }
+
+ #endif
+
+ return (total == 6 || total == 11 || total == 10);
+}
+
+void nxagentFlushConfigureWindow(void)
+{
+ ConfiguredWindowStruct *index;
+ XWindowChanges changes;
+ int i;
+ int j;
+
+ index = nxagentConfiguredWindowList;
+
+ while (index)
+ {
+ if (index -> next == NULL)
+ {
+ break;
+ }
+
+ index = index -> next;
+ }
+
+ while (index)
+ {
+ ConfiguredWindowStruct *tmp;
+
+ WindowPtr pWin = index -> pWin;
+ unsigned int valuemask = index -> valuemask;
+
+ if (pWin && valuemask)
+ {
+ nxagentConfigureWindow(pWin, valuemask);
+ }
+
+ tmp = index;
+
+ if (index == nxagentConfiguredWindowList)
+ {
+ free(tmp);
+ break;
+ }
+
+ index = index -> prev;
+ free(tmp);
+ }
+
+ nxagentConfiguredWindowList = NULL;
+
+ for (j = 0; j < nxagentExposeQueue.length; j++)
+ {
+ i = (nxagentExposeQueue.start + j) % EXPOSED_SIZE;
+
+ if (nxagentExposeQueue.exposures[i].synchronize == 1)
+ {
+ changes.x = nxagentExposeQueue.exposures[i].serial;
+ changes.y = -2;
+
+ #ifdef DEBUG
+ fprintf(stderr, "nxagentFlushConfigureWindow: Sending synch ConfigureWindow for "
+ "index [%d] serial [%d].\n", i, nxagentExposeQueue.exposures[i].serial);
+ #endif
+
+ XConfigureWindow(nxagentDisplay, nxagentConfiguredSynchroWindow,
+ CWX | CWY, &changes);
+
+ nxagentExposeQueue.exposures[i].synchronize = 0;
+ }
+ }
+
+ nxagentSendDeferredBackgroundExposures();
+
+ return;
+}
+
+void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind)
+{
+/*
+FIXME: Do we need this here?
+
+ nxagentFlushConfigureWindow();
+*/
+
+ return;
+}
+
+void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask)
+{
+ unsigned int mask;
+
+ mask = valuemask & (CWParent | CWX | CWY | CWWidth | CWHeight |
+ CWBorderWidth | CWStackingOrder | CW_Map | CW_Update | CW_Shape);
+
+ valuemask &= ~(CWParent | CWX | CWY | CWWidth | CWHeight | CWBorderWidth | CWStackingOrder);
+
+ if (mask & CWX &&
+ nxagentWindowPriv(pWin)->x !=
+ pWin->origin.x - wBorderWidth(pWin))
+ {
+ valuemask |= CWX;
+ }
+
+ if (mask & CWY &&
+ nxagentWindowPriv(pWin)->y !=
+ pWin->origin.y - wBorderWidth(pWin))
+ {
+ valuemask |= CWY;
+ }
+
+ if (mask & CWWidth &&
+ nxagentWindowPriv(pWin)->width !=
+ pWin->drawable.width)
+ {
+ valuemask |= CWWidth;
+ }
+
+ if (mask & CWHeight &&
+ nxagentWindowPriv(pWin)->height !=
+ pWin->drawable.height)
+ {
+ valuemask |= CWHeight;
+ }
+
+ if (mask & CWBorderWidth &&
+ nxagentWindowPriv(pWin)->borderWidth !=
+ pWin->borderWidth)
+ {
+ valuemask |= CWBorderWidth;
+ }
+
+ if (mask & CWStackingOrder &&
+ nxagentWindowPriv(pWin)->siblingAbove !=
+ nxagentWindowSiblingAbove(pWin))
+ {
+ valuemask |= CWStackingOrder;
+ }
+
+ if (nxagentConfiguredWindowList == NULL)
+ {
+ nxagentConfiguredWindowList = malloc(sizeof(ConfiguredWindowStruct));
+ nxagentConfiguredWindowList -> next = NULL;
+ nxagentConfiguredWindowList -> prev = NULL;
+
+ nxagentConfiguredWindowList -> pWin = pWin;
+ }
+ else
+ {
+ ConfiguredWindowStruct *tmp;
+
+ tmp = malloc(sizeof(ConfiguredWindowStruct));
+
+ tmp -> next = nxagentConfiguredWindowList;
+ nxagentConfiguredWindowList -> prev = tmp;
+ tmp -> prev = NULL;
+ nxagentConfiguredWindowList = tmp;
+ nxagentConfiguredWindowList -> pWin = pWin;
+ }
+
+ nxagentConfiguredWindowList -> valuemask = valuemask;
+
+ return;
+}
+
+void nxagentDeleteConfiguredWindow(WindowPtr pWin)
+{
+ ConfiguredWindowStruct *index, *previous, *tmp;
+
+ index = nxagentConfiguredWindowList;
+
+ while (index)
+ {
+ WindowPtr pDel = index -> pWin;
+
+ if (pDel == pWin)
+ {
+ if (index -> prev == NULL && index -> next == NULL)
+ {
+ free(nxagentConfiguredWindowList);
+ nxagentConfiguredWindowList = NULL;
+
+ return;
+ }
+ else if (index -> prev == NULL)
+ {
+ tmp = nxagentConfiguredWindowList;
+ index = nxagentConfiguredWindowList = tmp -> next;
+ free(tmp);
+ nxagentConfiguredWindowList -> prev = NULL;
+
+ continue;
+ }
+ else if (index -> next == NULL)
+ {
+ tmp = index;
+ index = index -> prev;
+ free(tmp);
+ index -> next = NULL;
+
+ return;
+ }
+
+ previous = index -> prev;
+ tmp = index;
+ index = index -> next;
+ previous -> next = index;
+ index -> prev = previous;
+ free(tmp);
+
+ continue;
+ }
+
+ index = index -> next;
+ }
+
+ return;
+}
+
+void nxagentAddStaticResizedWindow(WindowPtr pWin, unsigned long sequence, int offX, int offY)
+{
+ if (nxagentStaticResizedWindowList == NULL)
+ {
+ nxagentStaticResizedWindowList = malloc(sizeof(StaticResizedWindowStruct));
+ nxagentStaticResizedWindowList -> next = NULL;
+ nxagentStaticResizedWindowList -> prev = NULL;
+ }
+ else
+ {
+ StaticResizedWindowStruct *tmp;
+
+ tmp = malloc(sizeof(StaticResizedWindowStruct));
+
+ tmp -> next = nxagentStaticResizedWindowList;
+ nxagentStaticResizedWindowList -> prev = tmp;
+ tmp -> prev = NULL;
+ nxagentStaticResizedWindowList = tmp;
+ }
+
+ nxagentStaticResizedWindowList -> pWin = pWin;
+ nxagentStaticResizedWindowList -> sequence = sequence;
+ nxagentStaticResizedWindowList -> offX = offX;
+ nxagentStaticResizedWindowList -> offY = offY;
+}
+
+void nxagentDeleteStaticResizedWindow(unsigned long sequence)
+{
+ StaticResizedWindowStruct *index, *previous, *tmp;
+
+ index = nxagentStaticResizedWindowList;
+
+ while (index)
+ {
+ if (index -> sequence <= sequence)
+ {
+ if (index -> prev == NULL && index -> next == NULL)
+ {
+ free(nxagentStaticResizedWindowList);
+ nxagentStaticResizedWindowList = NULL;
+
+ return;
+ }
+ else if (index -> prev == NULL)
+ {
+ tmp = nxagentStaticResizedWindowList;
+ index = nxagentStaticResizedWindowList = tmp -> next;
+ free(tmp);
+ nxagentStaticResizedWindowList -> prev = NULL;
+
+ continue;
+ }
+ else if (index -> next == NULL)
+ {
+ tmp = index;
+ index = index -> prev;
+ free(tmp);
+ index -> next = NULL;
+
+ return;
+ }
+
+ previous = index -> prev;
+ tmp = index;
+ index = index -> next;
+ previous -> next = index;
+ index -> prev = previous;
+ free(tmp);
+
+ continue;
+ }
+
+ index = index -> next;
+ }
+
+ return;
+}
+
+StaticResizedWindowStruct *nxagentFindStaticResizedWindow(unsigned long sequence)
+{
+ StaticResizedWindowStruct *index;
+ StaticResizedWindowStruct *ret = NULL;
+
+ if (nxagentStaticResizedWindowList == NULL)
+ {
+ return NULL;
+ }
+
+ index = nxagentStaticResizedWindowList;
+
+ while (index && index -> sequence > sequence)
+ {
+ ret = index;
+ index = index -> next;
+ }
+
+ return ret;
+}
+
+void nxagentEmptyBackingStoreRegion(void * param0, XID param1, void * data_buffer)
+{
+ WindowPtr pWin = (WindowPtr) param0;
+
+ miBSWindowPtr pBackingStore = (miBSWindowPtr)pWin->backStorage;
+
+ if (pBackingStore != NULL)
+ {
+ RegionEmpty(&pBackingStore->SavedRegion);
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying saved region for window at [%p].\n", (void*) pWin);
+ #endif
+
+ if (pBackingStore -> pBackingPixmap != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentEmptyBackingStoreRegion: Emptying corrupted region for drawable at [%p].\n",
+ (void*) pBackingStore -> pBackingPixmap);
+ #endif
+
+ nxagentUnmarkCorruptedRegion((DrawablePtr) pBackingStore -> pBackingPixmap, NullRegion);
+ }
+ }
+}
+
+void nxagentEmptyAllBackingStoreRegions(void)
+{
+ if (nxagentLoopOverWindows(nxagentEmptyBackingStoreRegion) == 0)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "nxagentEmptyAllSavedRegions: Failed to empty backing store saved regions.\n");
+ #endif
+ }
+}
+
+void nxagentInitBSPixmapList(void)
+{
+ memset(nxagentBSPixmapList, 0, BSPIXMAPLIMIT * sizeof( StoringPixmapPtr));
+}
+
+int nxagentAddItemBSPixmapList(unsigned long id, PixmapPtr pPixmap, WindowPtr pWin, int bsx, int bsy)
+{
+ int i;
+
+ for (i = 0; i < BSPIXMAPLIMIT; i++)
+ {
+ if (nxagentBSPixmapList[i] == NULL)
+ {
+ nxagentBSPixmapList[i] = malloc(sizeof(StoringPixmapRec));
+
+ if (nxagentBSPixmapList[i] == NULL)
+ {
+ FatalError("nxagentAddItemBSPixmapList: Failed to allocate memory for nxagentBSPixmapList.\n");
+ }
+
+ nxagentBSPixmapList[i] -> storingPixmapId = id;
+ nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap;
+ nxagentBSPixmapList[i] -> pSavedWindow = pWin;
+ nxagentBSPixmapList[i] -> backingStoreX = bsx;
+ nxagentBSPixmapList[i] -> backingStoreY = bsy;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddItemBSPixmapList: Added Pixmap with id [%lu] to nxagentBSPixmapList.\n", id);
+ #endif
+
+ return 1;
+ }
+
+ if (nxagentBSPixmapList[i] -> storingPixmapId == id)
+ {
+ nxagentBSPixmapList[i] -> pStoringPixmap = pPixmap;
+ nxagentBSPixmapList[i] -> pSavedWindow = pWin;
+ nxagentBSPixmapList[i] -> backingStoreX = bsx;
+ nxagentBSPixmapList[i] -> backingStoreY = bsy;
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddItemBSPixmapList: Updated existing item for id [%lu].\n", id);
+ #endif
+
+ return 1;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentAddItemBSPixmapList: WARNING! List item full.\n");
+ #endif
+
+ return 0;
+}
+
+int nxagentRemoveItemBSPixmapList(unsigned long pixmapId)
+{
+ int i;
+ int j;
+
+ if (pixmapId == 0 || nxagentBSPixmapList[0] == NULL)
+ {
+ return 0;
+ }
+
+ for (i = 0; i < BSPIXMAPLIMIT; i++)
+ {
+ if ((nxagentBSPixmapList[i] != NULL) &&
+ (nxagentBSPixmapList[i] -> storingPixmapId == pixmapId))
+ {
+ free(nxagentBSPixmapList[i]);
+ nxagentBSPixmapList[i] = NULL;
+
+ if (i < BSPIXMAPLIMIT - 1)
+ {
+ for (j = i; j < BSPIXMAPLIMIT -1; j++)
+ {
+ nxagentBSPixmapList[j] = nxagentBSPixmapList[j + 1];
+ }
+
+ if (nxagentBSPixmapList[j] == nxagentBSPixmapList[j - 1])
+ {
+ nxagentBSPixmapList[j] = NULL;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemoveItemBSPixmapList: Removed Pixmap with id [%lu] from list.\n",
+ pixmapId);
+ #endif
+
+ return 1;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentRemoveItemBSPixmapList: WARNING! Can't remove item [%lu]: item not found.\n",
+ pixmapId);
+ #endif
+
+ return 0;
+}
+
+int nxagentEmptyBSPixmapList()
+{
+ int i;
+
+ for (i = 0; i < BSPIXMAPLIMIT; i++)
+ {
+ if (nxagentBSPixmapList[i] != NULL)
+ {
+ free(nxagentBSPixmapList[i]);
+ nxagentBSPixmapList[i] = NULL;
+ }
+ }
+
+ return 1;
+}
+
+StoringPixmapPtr nxagentFindItemBSPixmapList(unsigned long pixmapId)
+{
+ int i;
+
+ for (i = 0; i < BSPIXMAPLIMIT; i++)
+ {
+ if ((nxagentBSPixmapList[i] != NULL) &&
+ (nxagentBSPixmapList[i] -> storingPixmapId == pixmapId))
+ {
+ #ifdef TEST
+ fprintf(stderr, "nxagentFindItemBSPixmapList: pixmapId [%lu].\n", pixmapId);
+ fprintf(stderr, "nxagentFindItemBSPixmapList: nxagentBSPixmapList[%d] -> storingPixmapId [%lu].\n",
+ i, nxagentBSPixmapList[i] -> storingPixmapId);
+ #endif
+
+ return nxagentBSPixmapList[i];
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFindItemBSPixmapList: WARNING! Item not found.\n");
+ #endif
+
+ #ifdef TEST
+ fprintf(stderr, "nxagentFindItemBSPixmapList: Pixmap with id [%lu] not found.\n",
+ pixmapId);
+ fprintf(stderr, "nxagentBSPixmapList[%d] = [%p].\n",
+ i, (void *) nxagentBSPixmapList[i]);
+ #endif
+
+ return NULL;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/Windows.h b/nx-X11/programs/Xserver/hw/nxagent/Windows.h
new file mode 100644
index 000000000..8612cdf82
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/Windows.h
@@ -0,0 +1,328 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef __Window_H__
+#define __Window_H__
+
+#include "Options.h"
+#include "Rootless.h"
+#include "Pixmaps.h"
+
+#include "validate.h"
+
+typedef struct
+{
+ Window window;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned int borderWidth;
+ Window siblingAbove;
+ int backingStore;
+#ifdef SHAPE
+ RegionPtr boundingShape;
+ RegionPtr clipShape;
+#endif /* SHAPE */
+
+ void *pPicture;
+
+ /*
+ * Set if the window is mapped
+ * on the remote server.
+ */
+
+ int isMapped;
+
+ /*
+ * Set if the window on the remote
+ * server is redirected by using
+ * the composite extension.
+ */
+
+ int isRedirected;
+
+ int visibilityState;
+
+ RegionPtr corruptedRegion;
+
+ int hasTransparentChildren;
+
+ int containGlyphs;
+
+ int deferredBackgroundExpose;
+
+ XID corruptedId;
+
+ PixmapPtr synchronizationBitmap;
+
+ Time corruptedTimestamp;
+
+ SplitResourcePtr splitResource;
+
+} nxagentPrivWindowRec;
+
+typedef nxagentPrivWindowRec *nxagentPrivWindowPtr;
+
+typedef struct
+{
+ unsigned long storingPixmapId;
+
+ PixmapPtr pStoringPixmap;
+
+ WindowPtr pSavedWindow;
+
+ int backingStoreX;
+
+ int backingStoreY;
+
+} StoringPixmapRec;
+
+typedef StoringPixmapRec *StoringPixmapPtr;
+
+int nxagentAddItemBSPixmapList(unsigned long, PixmapPtr, WindowPtr, int, int);
+int nxagentRemoveItemBSPixmapList(unsigned long);
+void nxagentInitBSPixmapList(void);
+int nxagentEmptyBSPixmapList(void);
+StoringPixmapPtr nxagentFindItemBSPixmapList (unsigned long);
+
+extern int nxagentWindowPrivateIndex;
+
+#define nxagentWindowPriv(pWin) \
+ ((nxagentPrivWindowPtr)((pWin)->devPrivates[nxagentWindowPrivateIndex].ptr))
+
+#define nxagentWindow(pWin) (nxagentWindowPriv(pWin)->window)
+
+/*
+ * Window is either a child of our root
+ * or a child of the root of the real X
+ * server.
+ */
+
+#define nxagentWindowParent(pWin) \
+ (nxagentOption(Rootless) ? \
+ nxagentRootlessWindowParent(pWin) : \
+ ((pWin)->parent ? \
+ nxagentWindow((pWin)->parent) : \
+ nxagentDefaultWindows[pWin->drawable.pScreen->myNum]))
+
+/*
+ * True if this is a top level window.
+ */
+
+#define nxagentWindowTopLevel(pWin) \
+ (pWin && (pWin -> parent == NULL || \
+ pWin->parent == nxagentRootlessWindow))
+
+#define nxagentWindowSiblingAbove(pWin) \
+ ((pWin)->prevSib ? nxagentWindow((pWin)->prevSib) : None)
+
+#define nxagentWindowSiblingBelow(pWin) \
+ ((pWin)->nextSib ? nxagentWindow((pWin)->nextSib) : None)
+
+#define nxagentWindowCorruptedRegion(pWin) \
+ (nxagentWindowPriv(pWin) -> corruptedRegion)
+
+#define nxagentWindowContainGlyphs(pWin) \
+ (nxagentWindowPriv(pWin) -> containGlyphs)
+
+#define nxagentWindowTimestamp(pWin) \
+ (nxagentWindowPriv(pWin) -> corruptedTimestamp)
+
+#define nxagentWindowIsVisible(pWin) \
+ ((pWin) -> viewable == 1 && \
+ (pWin) -> drawable.class != InputOnly && \
+ (pWin) -> visibility != VisibilityFullyObscured)
+
+#define nxagentDefaultWindowIsVisible() \
+ (nxagentVisibility != VisibilityFullyObscured)
+
+#define CWParent CWSibling
+#define CWStackingOrder CWStackMode
+
+#define CW_Map (1 << 15)
+#define CW_Update (1 << 16)
+#define CW_Shape (1 << 17)
+#define CW_RootlessRestack (1 << 18)
+
+/*
+ * This force the agent to send exposures
+ * for all windows.
+ */
+
+#define nxagentRefreshScreen() \
+do\
+{\
+ nxagentRefreshWindows(screenInfo.screens[0]->root);\
+} while (0)
+
+WindowPtr nxagentWindowPtr(Window window);
+
+extern Atom serverCutProperty;
+
+/*
+ * If the rectangles in an exposed region exceed
+ * the number of 4, we let the function decide if
+ * it is better to send the window extents rather
+ * than the rectangles in the region.
+ */
+
+int nxagentExtentsPredicate(int total);
+
+/*
+ * Agent's nested window procedures. Look also
+ * at Rootless.h for the rootless counterparts.
+ */
+
+Bool nxagentCreateWindow(WindowPtr pWin);
+
+Bool nxagentDestroyWindow(WindowPtr pWin);
+
+Bool nxagentPositionWindow(WindowPtr pWin, int x, int y);
+
+Bool nxagentChangeWindowAttributes(WindowPtr pWin, unsigned long mask);
+
+Bool nxagentRealizeWindow(WindowPtr pWin);
+
+Bool nxagentUnrealizeWindow(WindowPtr pWin);
+
+Bool nxagentCheckIllegalRootMonitoring(WindowPtr pWin, Mask mask);
+
+void nxagentWindowExposures(WindowPtr pWin, RegionPtr pRgn, RegionPtr other_exposed);
+
+void nxagentPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what);
+
+void nxagentPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what);
+
+void nxagentCopyWindow(WindowPtr pWin, xPoint oldOrigin, RegionPtr oldRegion);
+
+void nxagentClipNotify(WindowPtr pWin, int dx, int dy);
+
+void nxagentRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
+
+void nxagentReparentWindow(WindowPtr pWin, WindowPtr pOldParent);
+
+void nxagentRefreshWindows(WindowPtr pWin);
+
+void nxagentSetTopLevelEventMask(WindowPtr pWin);
+
+void nxagentSwitchFullscreen(ScreenPtr pScreen, Bool switchOn);
+
+void nxagentSwitchAllScreens(ScreenPtr pScreen, Bool switchOn);
+
+void nxagentMoveViewport(ScreenPtr pScreen, int hShift, int vShift);
+
+#ifdef VIEWPORT_FRAME
+
+void nxagentUpdateViewportFrame(int x, int y, int w, int h);
+
+#else /* #ifdef VIEWPORT_FRAME */
+
+#define nxagentUpdateViewportFrame(x, y, w, h)
+
+#endif /* #ifdef VIEWPORT_FRAME */
+
+void nxagentUnmapWindows(void);
+
+void nxagentMapDefaultWindows(void);
+
+Bool nxagentSetWindowCursors(void *p0);
+
+/*
+ * The ConfigureWindow procedure has not
+ * a pointer in the screen structure.
+ */
+
+void nxagentConfigureWindow(WindowPtr pWin, unsigned int mask);
+
+/*
+ * Used to track nxagent window's visibility.
+ */
+
+extern int nxagentVisibility;
+extern unsigned long nxagentVisibilityTimeout;
+extern Bool nxagentVisibilityStop;
+
+/*
+ * Return the pointer to the window given the
+ * remote id. It tries to match the id from
+ * the last matched window before iterating
+ * through the hierarchy.
+ */
+
+WindowPtr nxagentGetWindowFromID(Window id);
+
+/*
+ * Handle the shape bitmap for windows.
+ */
+
+#ifdef SHAPE
+
+void nxagentShapeWindow(WindowPtr pWin);
+
+#endif
+
+extern Window nxagentConfiguredSynchroWindow;
+extern Bool nxagentExposeArrayIsInitialized;
+
+typedef struct _ConfiguredWindow
+{
+ WindowPtr pWin;
+ struct _ConfiguredWindow *next;
+ struct _ConfiguredWindow *prev;
+ unsigned int valuemask;
+} ConfiguredWindowStruct;
+
+ConfiguredWindowStruct *nxagentConfiguredWindowList;
+
+typedef struct _StaticResizedWindow
+{
+ WindowPtr pWin;
+ struct _StaticResizedWindow *next;
+ struct _StaticResizedWindow *prev;
+ unsigned long sequence;
+ int offX;
+ int offY;
+} StaticResizedWindowStruct;
+
+StaticResizedWindowStruct *nxagentStaticResizedWindowList;
+
+void nxagentPostValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind);
+
+void nxagentFlushConfigureWindow(void);
+
+void nxagentAddConfiguredWindow(WindowPtr pWin, unsigned int valuemask);
+
+void nxagentDeleteConfiguredWindow(WindowPtr pWin);
+
+void nxagentAddStaticResizedWindow(WindowPtr pWin, unsigned long sequence, int offX, int offY);
+
+void nxagentDeleteStaticResizedWindow(unsigned long sequence);
+
+StaticResizedWindowStruct *nxagentFindStaticResizedWindow(unsigned long sequence);
+
+void nxagentEmptyAllBackingStoreRegions(void);
+
+#endif /* __Window_H__ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xcomposite_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xcomposite_nxagent.h
new file mode 100644
index 000000000..ba3668015
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xcomposite_nxagent.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+/*
+ * Copyright © 2003 Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+/*
+ * This file is a reduced version of the header file of
+ * <X11/extensions/Xcomposite.h>
+ *
+ * This copy of code has been introduced to allow a clear namespace
+ * separation between <X11/...> and <nx-X11/...> header files.
+ *
+ * This version of the Xcomposite library header file only contains symbols
+ * required by nxagent and strictly avoids indirectly including
+ * from an X11 library that is also shipped in nx-X11/lib/.
+ *
+ * When using <X11/extensions/Xcomposite.h> instead for inclusion in
+ * nxagent, it will attempt pulling in the <X11/extensions/Xlib.h>.
+ * However, the headers of the same name from <nx-X11/...> should be
+ * used instead.
+ *
+ * FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this
+ * hack can be removed.
+ *
+ * 2016/04/07, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+ */
+
+#ifndef _XCOMPOSITE_H_
+#define _XCOMPOSITE_H_
+
+#include <X11/extensions/composite.h>
+#include <nx-X11/Xfuncproto.h>
+
+/*
+ * This revision number also appears in configure.ac, they have
+ * to be manually synchronized
+ */
+#define XCOMPOSITE_MAJOR COMPOSITE_MAJOR
+#define XCOMPOSITE_MINOR COMPOSITE_MINOR
+#define XCOMPOSITE_REVISION 2
+#define XCOMPOSITE_VERSION ((XCOMPOSITE_MAJOR * 10000) + (XCOMPOSITE_MINOR * 100) + (XCOMPOSITE_REVISION))
+
+_XFUNCPROTOBEGIN
+
+Bool XCompositeQueryExtension (Display *dpy,
+ int *event_base_return,
+ int *error_base_return);
+
+Status XCompositeQueryVersion (Display *dpy,
+ int *major_version_return,
+ int *minor_version_return);
+
+void
+XCompositeRedirectWindow (Display *dpy, Window window, int update);
+
+void
+XCompositeRedirectSubwindows (Display *dpy, Window window, int update);
+
+void
+XCompositeUnredirectWindow (Display *dpy, Window window, int update);
+
+void
+XCompositeUnredirectSubwindows (Display *dpy, Window window, int update);
+
+_XFUNCPROTOEND
+
+#endif /* _XCOMPOSITE_H_ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xfixes_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xfixes_nxagent.h
new file mode 100644
index 000000000..cbe64fbba
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xfixes_nxagent.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2011 Red Hat, Inc.
+ *
+ * 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, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+/*
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+/*
+ * This file is a reduced version of the header file of
+ * <X11/extensions/Xfixes.h>
+ *
+ * This copy of code has been introduced to allow a clear namespace
+ * separation between <X11/...> and <nx-X11/...> header files.
+ *
+ * This version of the Xfixes library header file only contains symbols
+ * required by nxagent and strictly avoids indirectly including
+ * from an X11 library that is also shipped in nx-X11/lib/.
+ *
+ * When using <X11/extensions/Xfixes.h> instead for inclusion in
+ * nxagent, it will attempt pulling in the <X11/extensions/Xlib.h>.
+ * However, the headers of the same name from <nx-X11/...> should be
+ * used instead.
+ *
+ * FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this
+ * hack can be removed.
+ *
+ * 2015/12/28, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+ */
+
+#ifndef _XFIXES_H_
+#define _XFIXES_H_
+
+typedef struct {
+ int type; /* event base */
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ Window window;
+ int subtype;
+ Window owner;
+ Atom selection;
+ Time timestamp;
+ Time selection_timestamp;
+} XFixesSelectionNotifyEvent;
+
+void
+XFixesSelectSelectionInput (Display *dpy,
+ Window win,
+ Atom selection,
+ unsigned long eventMask);
+
+#endif /* _XFIXES_H_ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xinerama_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xinerama_nxagent.h
new file mode 100644
index 000000000..210c4b5e7
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xinerama_nxagent.h
@@ -0,0 +1,74 @@
+/*
+
+Copyright 2003 The Open Group
+
+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.
+
+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 THE
+OPEN GROUP 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.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#ifndef _Xinerama_h
+#define _Xinerama_h
+
+#include <nx-X11/Xlib.h>
+
+typedef struct {
+ int screen_number;
+ short x_org;
+ short y_org;
+ short width;
+ short height;
+} XineramaScreenInfo;
+
+_XFUNCPROTOBEGIN
+
+Bool XineramaQueryExtension (
+ Display *dpy,
+ int *event_base,
+ int *error_base
+);
+
+Status XineramaQueryVersion(
+ Display *dpy,
+ int *major_versionp,
+ int *minor_versionp
+);
+
+Bool XineramaIsActive(Display *dpy);
+
+
+/*
+ Returns the number of heads and a pointer to an array of
+ structures describing the position and size of the individual
+ heads. Returns NULL and number = 0 if Xinerama is not active.
+
+ Returned array should be freed with XFree().
+*/
+
+XineramaScreenInfo *
+XineramaQueryScreens(
+ Display *dpy,
+ int *number
+);
+
+_XFUNCPROTOEND
+
+#endif /* _Xinerama_h */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrandr_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrandr_nxagent.h
new file mode 100644
index 000000000..02f3356e4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrandr_nxagent.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2000 Compaq Computer Corporation, Inc.
+ * Copyright © 2002 Hewlett-Packard Company, Inc.
+ * Copyright © 2006 Intel Corporation
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * 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
+ */
+
+/*
+ * This file is a reduced version of the header file of
+ * <X11/extensions/Xrandr.h>
+ *
+ * This copy of code has been introduced to allow a clear namespace
+ * separation between <X11/...> and <nx-X11/...> header files.
+ *
+ * This version of the Xrandr library header file only contains symbols
+ * required by nxagent and strictly avoids indirectly including
+ * from an X11 library that is also shipped in nx-X11/lib/.
+ *
+ * When using <X11/extensions/Xrandr.h> instead for inclusion in
+ * nxagent, it will attempt pulling in the <X11/extensions/Xrender.h>
+ * header which in turn will include <X11/Xlib.h>. However, the headers of
+ * the same name from <nx-X11/...> should be used instead.
+ *
+ * FIXME: Once the nxagent Xserver starts using libXrender from X.Org, this
+ * hack can be removed.
+ *
+ * 2015/06/26, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+ */
+
+#ifndef _XRANDR_H_
+#define _XRANDR_H_
+
+#include <nx-X11/extensions/randr.h>
+#include <nx-X11/Xfuncproto.h>
+
+_XFUNCPROTOBEGIN
+
+/*
+ * Events.
+ */
+
+typedef struct {
+ int type; /* event base */
+ unsigned long serial; /* # of last request processed by server */
+ Bool send_event; /* true if this came from a SendEvent request */
+ Display *display; /* Display the event was read from */
+ Window window; /* window which selected for this event */
+ Window root; /* Root window for changed screen */
+ Time timestamp; /* when the screen change occurred */
+ Time config_timestamp; /* when the last configuration change */
+ SizeID size_index;
+ SubpixelOrder subpixel_order;
+ Rotation rotation;
+ int width;
+ int height;
+ int mwidth;
+ int mheight;
+} XRRScreenChangeNotifyEvent;
+
+_XFUNCPROTOEND
+
+#endif /* _XRANDR_H_ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrender_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrender_nxagent.h
new file mode 100644
index 000000000..488132172
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrender_nxagent.h
@@ -0,0 +1,528 @@
+/*
+ *
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+#ifndef _XRENDER_H_
+#define _XRENDER_H_
+
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xfuncproto.h>
+#include <nx-X11/Xosdefs.h>
+#include <nx-X11/Xutil.h>
+
+#include <nx-X11/extensions/render.h>
+
+typedef struct {
+ short red;
+ short redMask;
+ short green;
+ short greenMask;
+ short blue;
+ short blueMask;
+ short alpha;
+ short alphaMask;
+} XRenderDirectFormat;
+
+typedef struct {
+ PictFormat id;
+ int type;
+ int depth;
+ XRenderDirectFormat direct;
+ Colormap colormap;
+} XRenderPictFormat;
+
+#define PictFormatID (1 << 0)
+#define PictFormatType (1 << 1)
+#define PictFormatDepth (1 << 2)
+#define PictFormatRed (1 << 3)
+#define PictFormatRedMask (1 << 4)
+#define PictFormatGreen (1 << 5)
+#define PictFormatGreenMask (1 << 6)
+#define PictFormatBlue (1 << 7)
+#define PictFormatBlueMask (1 << 8)
+#define PictFormatAlpha (1 << 9)
+#define PictFormatAlphaMask (1 << 10)
+#define PictFormatColormap (1 << 11)
+
+typedef struct _XRenderPictureAttributes {
+ int repeat;
+ Picture alpha_map;
+ int alpha_x_origin;
+ int alpha_y_origin;
+ int clip_x_origin;
+ int clip_y_origin;
+ Pixmap clip_mask;
+ Bool graphics_exposures;
+ int subwindow_mode;
+ int poly_edge;
+ int poly_mode;
+ Atom dither;
+ Bool component_alpha;
+} XRenderPictureAttributes;
+
+typedef struct {
+ unsigned short red;
+ unsigned short green;
+ unsigned short blue;
+ unsigned short alpha;
+} XRenderColor;
+
+typedef struct _XGlyphInfo {
+ unsigned short width;
+ unsigned short height;
+ short x;
+ short y;
+ short xOff;
+ short yOff;
+} XGlyphInfo;
+
+typedef struct _XGlyphElt8 {
+ GlyphSet glyphset;
+ _Xconst char *chars;
+ int nchars;
+ int xOff;
+ int yOff;
+} XGlyphElt8;
+
+typedef struct _XGlyphElt16 {
+ GlyphSet glyphset;
+ _Xconst unsigned short *chars;
+ int nchars;
+ int xOff;
+ int yOff;
+} XGlyphElt16;
+
+typedef struct _XGlyphElt32 {
+ GlyphSet glyphset;
+ _Xconst unsigned int *chars;
+ int nchars;
+ int xOff;
+ int yOff;
+} XGlyphElt32;
+
+typedef double XDouble;
+
+typedef struct _XPointDouble {
+ XDouble x, y;
+} XPointDouble;
+
+#define XDoubleToFixed(f) ((XFixed) ((f) * 65536))
+#define XFixedToDouble(f) (((XDouble) (f)) / 65536)
+
+typedef int XFixed;
+
+typedef struct _XPointFixed {
+ XFixed x, y;
+} XPointFixed;
+
+typedef struct _XLineFixed {
+ XPointFixed p1, p2;
+} XLineFixed;
+
+typedef struct _XTriangle {
+ XPointFixed p1, p2, p3;
+} XTriangle;
+
+typedef struct _XCircle {
+ XFixed x;
+ XFixed y;
+ XFixed radius;
+} XCircle;
+
+typedef struct _XTrapezoid {
+ XFixed top, bottom;
+ XLineFixed left, right;
+} XTrapezoid;
+
+typedef struct _XTransform {
+ XFixed matrix[3][3];
+} XTransform;
+
+typedef struct _XFilters {
+ int nfilter;
+ char **filter;
+ int nalias;
+ short *alias;
+} XFilters;
+
+typedef struct _XIndexValue {
+ unsigned long pixel;
+ unsigned short red, green, blue, alpha;
+} XIndexValue;
+
+typedef struct _XAnimCursor {
+ Cursor cursor;
+ unsigned long delay;
+} XAnimCursor;
+
+typedef struct _XSpanFix {
+ XFixed left, right, y;
+} XSpanFix;
+
+typedef struct _XTrap {
+ XSpanFix top, bottom;
+} XTrap;
+
+typedef struct _XLinearGradient {
+ XPointFixed p1;
+ XPointFixed p2;
+} XLinearGradient;
+
+typedef struct _XRadialGradient {
+ XCircle inner;
+ XCircle outer;
+} XRadialGradient;
+
+typedef struct _XConicalGradient {
+ XPointFixed center;
+ XFixed angle; /* in degrees */
+} XConicalGradient;
+
+_XFUNCPROTOBEGIN
+
+Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep);
+
+Status XRenderQueryVersion (Display *dpy,
+ int *major_versionp,
+ int *minor_versionp);
+
+Status XRenderQueryFormats (Display *dpy);
+
+int XRenderQuerySubpixelOrder (Display *dpy, int screen);
+
+Bool XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel);
+
+XRenderPictFormat *
+XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual);
+
+XRenderPictFormat *
+XRenderFindFormat (Display *dpy,
+ unsigned long mask,
+ _Xconst XRenderPictFormat *templ,
+ int count);
+
+#define PictStandardARGB32 0
+#define PictStandardRGB24 1
+#define PictStandardA8 2
+#define PictStandardA4 3
+#define PictStandardA1 4
+#define PictStandardNUM 5
+
+XRenderPictFormat *
+XRenderFindStandardFormat (Display *dpy,
+ int format);
+
+XIndexValue *
+XRenderQueryPictIndexValues(Display *dpy,
+ _Xconst XRenderPictFormat *format,
+ int *num);
+
+Picture
+XRenderCreatePicture (Display *dpy,
+ Drawable drawable,
+ _Xconst XRenderPictFormat *format,
+ unsigned long valuemask,
+ _Xconst XRenderPictureAttributes *attributes);
+
+void
+XRenderChangePicture (Display *dpy,
+ Picture picture,
+ unsigned long valuemask,
+ _Xconst XRenderPictureAttributes *attributes);
+
+void
+XRenderSetPictureClipRectangles (Display *dpy,
+ Picture picture,
+ int xOrigin,
+ int yOrigin,
+ _Xconst XRectangle *rects,
+ int n);
+
+void
+XRenderSetPictureClipRegion (Display *dpy,
+ Picture picture,
+ Region r);
+
+void
+XRenderSetPictureTransform (Display *dpy,
+ Picture picture,
+ XTransform *transform);
+
+void
+XRenderFreePicture (Display *dpy,
+ Picture picture);
+
+void
+XRenderComposite (Display *dpy,
+ int op,
+ Picture src,
+ Picture mask,
+ Picture dst,
+ int src_x,
+ int src_y,
+ int mask_x,
+ int mask_y,
+ int dst_x,
+ int dst_y,
+ unsigned int width,
+ unsigned int height);
+
+GlyphSet
+XRenderCreateGlyphSet (Display *dpy, _Xconst XRenderPictFormat *format);
+
+GlyphSet
+XRenderReferenceGlyphSet (Display *dpy, GlyphSet existing);
+
+void
+XRenderFreeGlyphSet (Display *dpy, GlyphSet glyphset);
+
+void
+XRenderAddGlyphs (Display *dpy,
+ GlyphSet glyphset,
+ _Xconst Glyph *gids,
+ _Xconst XGlyphInfo *glyphs,
+ int nglyphs,
+ _Xconst char *images,
+ int nbyte_images);
+
+void
+XRenderFreeGlyphs (Display *dpy,
+ GlyphSet glyphset,
+ _Xconst Glyph *gids,
+ int nglyphs);
+
+void
+XRenderCompositeString8 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ GlyphSet glyphset,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst char *string,
+ int nchar);
+
+void
+XRenderCompositeString16 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ GlyphSet glyphset,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst unsigned short *string,
+ int nchar);
+
+void
+XRenderCompositeString32 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ GlyphSet glyphset,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst unsigned int *string,
+ int nchar);
+
+void
+XRenderCompositeText8 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst XGlyphElt8 *elts,
+ int nelt);
+
+void
+XRenderCompositeText16 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst XGlyphElt16 *elts,
+ int nelt);
+
+void
+XRenderCompositeText32 (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst XGlyphElt32 *elts,
+ int nelt);
+
+void
+XRenderFillRectangle (Display *dpy,
+ int op,
+ Picture dst,
+ _Xconst XRenderColor *color,
+ int x,
+ int y,
+ unsigned int width,
+ unsigned int height);
+
+void
+XRenderFillRectangles (Display *dpy,
+ int op,
+ Picture dst,
+ _Xconst XRenderColor *color,
+ _Xconst XRectangle *rectangles,
+ int n_rects);
+
+void
+XRenderCompositeTrapezoids (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ _Xconst XTrapezoid *traps,
+ int ntrap);
+
+void
+XRenderCompositeTriangles (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ _Xconst XTriangle *triangles,
+ int ntriangle);
+
+void
+XRenderCompositeTriStrip (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ _Xconst XPointFixed *points,
+ int npoint);
+
+void
+XRenderCompositeTriFan (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ _Xconst XPointFixed *points,
+ int npoint);
+
+void
+XRenderCompositeDoublePoly (Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ int xDst,
+ int yDst,
+ _Xconst XPointDouble *fpoints,
+ int npoints,
+ int winding);
+Status
+XRenderParseColor(Display *dpy,
+ char *spec,
+ XRenderColor *def);
+
+Cursor
+XRenderCreateCursor (Display *dpy,
+ Picture source,
+ unsigned int x,
+ unsigned int y);
+
+XFilters *
+XRenderQueryFilters (Display *dpy, Drawable drawable);
+
+void
+XRenderSetPictureFilter (Display *dpy,
+ Picture picture,
+ const char *filter,
+ XFixed *params,
+ int nparams);
+
+Cursor
+XRenderCreateAnimCursor (Display *dpy,
+ int ncursor,
+ XAnimCursor *cursors);
+
+
+void
+XRenderAddTraps (Display *dpy,
+ Picture picture,
+ int xOff,
+ int yOff,
+ _Xconst XTrap *traps,
+ int ntrap);
+
+Picture XRenderCreateSolidFill (Display *dpy,
+ const XRenderColor *color);
+
+Picture XRenderCreateLinearGradient (Display *dpy,
+ const XLinearGradient *gradient,
+ const XFixed *stops,
+ const XRenderColor *colors,
+ int nstops);
+
+Picture XRenderCreateRadialGradient (Display *dpy,
+ const XRadialGradient *gradient,
+ const XFixed *stops,
+ const XRenderColor *colors,
+ int nstops);
+
+Picture XRenderCreateConicalGradient (Display *dpy,
+ const XConicalGradient *gradient,
+ const XFixed *stops,
+ const XRenderColor *colors,
+ int nstops);
+
+_XFUNCPROTOEND
+
+#endif /* _XRENDER_H_ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrenderint_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrenderint_nxagent.h
new file mode 100644
index 000000000..ff14aa26a
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrenderint_nxagent.h
@@ -0,0 +1,106 @@
+/*
+ *
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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 SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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: Keith Packard, SuSE, Inc.
+ */
+
+#ifndef _XRENDERINT_H_
+#define _XRENDERINT_H_
+
+#include <nx-X11/Xlibint.h>
+#include <nx-X11/Xutil.h>
+#include <nx-X11/extensions/renderproto.h>
+#include "Xrender_nxagent.h"
+
+typedef struct {
+ Visual *visual;
+ XRenderPictFormat *format;
+} XRenderVisual;
+
+typedef struct {
+ int depth;
+ int nvisuals;
+ XRenderVisual *visuals;
+} XRenderDepth;
+
+typedef struct {
+ XRenderDepth *depths;
+ int ndepths;
+ XRenderPictFormat *fallback;
+ int subpixel;
+} XRenderScreen;
+
+typedef struct _XRenderInfo {
+ int major_version;
+ int minor_version;
+ XRenderPictFormat *format;
+ int nformat;
+ XRenderScreen *screen;
+ int nscreen;
+ XRenderDepth *depth;
+ int ndepth;
+ XRenderVisual *visual;
+ int nvisual;
+ int *subpixel;
+ int nsubpixel;
+ char **filter;
+ int nfilter;
+ short *filter_alias;
+ int nfilter_alias;
+} XRenderInfo;
+
+/* replaces XRenderExtDisplayInfo */
+typedef struct _XRenderExtDisplayInfo {
+ struct _XRenderExtDisplayInfo *next; /* keep a linked list */
+ Display *display; /* which display this is */
+ XExtCodes *codes; /* the extension protocol codes */
+ XRenderInfo *info; /* extra data for the extension to use */
+} XRenderExtDisplayInfo;
+
+/* replaces XExtensionInfo */
+typedef struct _XRenderExtInfo {
+ XRenderExtDisplayInfo *head; /* start of the list */
+ XRenderExtDisplayInfo *cur; /* most recently used */
+ int ndisplays; /* number of displays */
+} XRenderExtInfo;
+
+extern XRenderExtInfo XRenderExtensionInfo;
+extern char XRenderExtensionName[];
+
+XRenderExtDisplayInfo *
+XRenderFindDisplay (Display *dpy);
+
+#define RenderHasExtension(i) ((i) && ((i)->codes))
+
+#define RenderCheckExtension(dpy,i,val) \
+ if (!RenderHasExtension(i)) { return val; }
+
+#define RenderSimpleCheckExtension(dpy,i) \
+ if (!RenderHasExtension(i)) { return; }
+
+/*
+ * Xlib uses long for 32-bit values. Xrender uses int. This
+ * matters on alpha. Note that this macro assumes that int is 32 bits.
+ */
+
+#define DataInt32(dpy,d,len) Data(dpy,(char *) (d),len)
+
+#endif /* _XRENDERINT_H_ */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/X11/include/xpm_nxagent.h b/nx-X11/programs/Xserver/hw/nxagent/X11/include/xpm_nxagent.h
new file mode 100644
index 000000000..b02e5a913
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/X11/include/xpm_nxagent.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 1989-95 GROUPE BULL
+ *
+ * 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, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * 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
+ * GROUPE BULL 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.
+ *
+ * Except as contained in this notice, the name of GROUPE BULL shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from GROUPE BULL.
+ */
+
+/*****************************************************************************\
+* xpm.h: *
+* *
+* XPM library *
+* Include file *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+/*
+ * This file is a reduced version of the header file of
+ * <X11/xpm.h>
+ *
+ * This copy of code has been introduced to allow a clear namespace
+ * separation between <X11/...> and <nx-X11/...> header files.
+ *
+ * This version of the Xpm library header file only contains symbols
+ * required by nxagent and strictly avoids indirectly including
+ * from an X11 library that is also shipped in nx-X11/lib/.
+ *
+ * When using <X11/xpm.h> instead for inclusion in nxagent, it will
+ * attempt pulling in the <X11/extensions/Xlib.h> header file.
+ * However, the headers of the same name from <nx-X11/...> should be
+ * used instead.
+ *
+ * FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this
+ * hack can be removed.
+ *
+ * 2015/06/26, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+ */
+
+#ifndef XPM_h
+#define XPM_h
+
+/*
+ * first some identification numbers:
+ * the version and revision numbers are determined with the following rule:
+ * SO Major number = LIB minor version number.
+ * SO Minor number = LIB sub-minor version number.
+ * e.g: Xpm version 3.2f
+ * we forget the 3 which is the format number, 2 gives 2, and f gives 6.
+ * thus we have XpmVersion = 2 and XpmRevision = 6
+ * which gives SOXPMLIBREV = 2.6
+ *
+ * Then the XpmIncludeVersion number is built from these numbers.
+ */
+#define XpmFormat 3
+#define XpmVersion 4
+#define XpmRevision 11
+#define XpmIncludeVersion ((XpmFormat * 100 + XpmVersion) * 100 + XpmRevision)
+
+#ifndef XPM_NUMBERS
+
+/* let's define Pixel if it is not done yet */
+#if ! defined(_XtIntrinsic_h) && ! defined(PIXEL_ALREADY_TYPEDEFED)
+typedef unsigned long Pixel; /* Index into colormap */
+# define PIXEL_ALREADY_TYPEDEFED
+#endif
+
+/* include headers from <nx-X11/...> instead of <X11/...> */
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xutil.h>
+
+/* Return ErrorStatus codes:
+ * null if full success
+ * positive if partial success
+ * negative if failure
+ */
+
+#define XpmColorError 1
+#define XpmSuccess 0
+#define XpmOpenFailed -1
+#define XpmFileInvalid -2
+#define XpmNoMemory -3
+#define XpmColorFailed -4
+
+typedef struct {
+ char *name; /* Symbolic color name */
+ char *value; /* Color value */
+ Pixel pixel; /* Color pixel */
+} XpmColorSymbol;
+
+typedef struct {
+ char *name; /* name of the extension */
+ unsigned int nlines; /* number of lines in this extension */
+ char **lines; /* pointer to the extension array of strings */
+} XpmExtension;
+
+typedef struct {
+ char *string; /* characters string */
+ char *symbolic; /* symbolic name */
+ char *m_color; /* monochrom default */
+ char *g4_color; /* 4 level grayscale default */
+ char *g_color; /* other level grayscale default */
+ char *c_color; /* color default */
+} XpmColor;
+
+typedef struct {
+ unsigned int width; /* image width */
+ unsigned int height; /* image height */
+ unsigned int cpp; /* number of characters per pixel */
+ unsigned int ncolors; /* number of colors */
+ XpmColor *colorTable; /* list of related colors */
+ unsigned int *data; /* image data */
+} XpmImage;
+
+typedef struct {
+ unsigned long valuemask; /* Specifies which attributes are defined */
+ char *hints_cmt; /* Comment of the hints section */
+ char *colors_cmt; /* Comment of the colors section */
+ char *pixels_cmt; /* Comment of the pixels section */
+ unsigned int x_hotspot; /* Returns the x hotspot's coordinate */
+ unsigned int y_hotspot; /* Returns the y hotspot's coordinate */
+ unsigned int nextensions; /* number of extensions */
+ XpmExtension *extensions; /* pointer to array of extensions */
+} XpmInfo;
+
+typedef int (*XpmAllocColorFunc)(
+ Display* /* display */,
+ Colormap /* colormap */,
+ char* /* colorname */,
+ XColor* /* xcolor */,
+ void* /* closure */
+);
+
+typedef int (*XpmFreeColorsFunc)(
+ Display* /* display */,
+ Colormap /* colormap */,
+ Pixel* /* pixels */,
+ int /* npixels */,
+ void* /* closure */
+);
+
+
+/* required struct for hw/nxagent/Holder.c */
+typedef struct {
+ unsigned long valuemask; /* Specifies which attributes are
+ defined */
+
+ Visual *visual; /* Specifies the visual to use */
+ Colormap colormap; /* Specifies the colormap to use */
+ unsigned int depth; /* Specifies the depth */
+ unsigned int width; /* Returns the width of the created
+ pixmap */
+ unsigned int height; /* Returns the height of the created
+ pixmap */
+ unsigned int x_hotspot; /* Returns the x hotspot's
+ coordinate */
+ unsigned int y_hotspot; /* Returns the y hotspot's
+ coordinate */
+ unsigned int cpp; /* Specifies the number of char per
+ pixel */
+ Pixel *pixels; /* List of used color pixels */
+ unsigned int npixels; /* Number of used pixels */
+ XpmColorSymbol *colorsymbols; /* List of color symbols to override */
+ unsigned int numsymbols; /* Number of symbols */
+ char *rgb_fname; /* RGB text file name */
+ unsigned int nextensions; /* Number of extensions */
+ XpmExtension *extensions; /* List of extensions */
+
+ unsigned int ncolors; /* Number of colors */
+ XpmColor *colorTable; /* List of colors */
+/* 3.2 backward compatibility code */
+ char *hints_cmt; /* Comment of the hints section */
+ char *colors_cmt; /* Comment of the colors section */
+ char *pixels_cmt; /* Comment of the pixels section */
+/* end 3.2 bc */
+ unsigned int mask_pixel; /* Color table index of transparent
+ color */
+
+ /* Color Allocation Directives */
+ Bool exactColors; /* Only use exact colors for visual */
+ unsigned int closeness; /* Allowable RGB deviation */
+ unsigned int red_closeness; /* Allowable red deviation */
+ unsigned int green_closeness; /* Allowable green deviation */
+ unsigned int blue_closeness; /* Allowable blue deviation */
+ int color_key; /* Use colors from this color set */
+
+ Pixel *alloc_pixels; /* Returns the list of alloc'ed color
+ pixels */
+ int nalloc_pixels; /* Returns the number of alloc'ed
+ color pixels */
+
+ Bool alloc_close_colors; /* Specify whether close colors should
+ be allocated using XAllocColor
+ or not */
+ int bitmap_format; /* Specify the format of 1bit depth
+ images: ZPixmap or XYBitmap */
+
+ /* Color functions */
+ XpmAllocColorFunc alloc_color; /* Application color allocator */
+ XpmFreeColorsFunc free_colors; /* Application color de-allocator */
+ void *color_closure; /* Application private data to pass to
+ alloc_color and free_colors */
+
+} XpmAttributes;
+
+/* XpmAttributes value masks bits */
+
+/* required masks bits for hw/nxagent/Holder.c */
+#define XpmDepth (1L<<2)
+#define XpmSize (1L<<3) /* width & height */
+
+/* macros for forward declarations of functions with prototypes */
+#define FUNC(f, t, p) extern t f p
+#define LFUNC(f, t, p) static t f p
+
+
+/*
+ * functions declarations (for building nxagent against system wide libXpm4,
+ * but also against libNX_X11 (as opposed to system-wide libX11).
+ */
+
+_XFUNCPROTOBEGIN
+
+/* Keep for hw/nxagent/Holder.c */
+FUNC(XpmCreatePixmapFromData, int, (Display *display,
+ Drawable d,
+ char **data,
+ Pixmap *pixmap_return,
+ Pixmap *shapemask_return,
+ XpmAttributes *attributes));
+/* Keep for hw/nxagent/Display.c */
+FUNC(XpmReadFileToPixmap, int, (Display *display,
+ Drawable d,
+ const char *filename,
+ Pixmap *pixmap_return,
+ Pixmap *shapemask_return,
+ XpmAttributes *attributes));
+
+_XFUNCPROTOEND
+
+#endif /* XPM_NUMBERS */
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c
new file mode 100644
index 000000000..11450d69d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.c
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Alpha.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define ALPHA_COMPRESSION_LEVEL 1
+#define ALPHA_COMPRESSION_THRESHOLD 32
+#define ALPHA_COMPRESSION_STRATEGY Z_RLE
+
+static int alphaCompressionLevel = ALPHA_COMPRESSION_LEVEL;
+static int alphaCompressionThreshold = ALPHA_COMPRESSION_THRESHOLD;
+static int alphaCompressionStrategy = ALPHA_COMPRESSION_STRATEGY;
+
+char *AlphaCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
+{
+ return ZCompressData(data, size, alphaCompressionThreshold, alphaCompressionLevel,
+ alphaCompressionStrategy, compressed_size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h
new file mode 100644
index 000000000..d7ac4e78e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Alpha.h
@@ -0,0 +1,45 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Alpha_H
+#define Alpha_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *AlphaCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Alpha_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c
new file mode 100644
index 000000000..d906118d0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.c
@@ -0,0 +1,120 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Compext.h"
+
+#include "Bitmap.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+char *BitmapCompressData(XImage *image, unsigned int *size)
+{
+ if (image -> bits_per_pixel != 32)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******BitmapCompressData: Nothing to do with image of [%d] bpp and size [%d].\n",
+ image -> bits_per_pixel, image -> bytes_per_line * image -> height);
+ #endif
+
+ *size = image -> bytes_per_line * image -> height;
+
+ return image -> data;
+ }
+ else
+ {
+ /*
+ * Remove the 4th byte from the bitmap.
+ */
+
+ char *data;
+
+ char *next_src;
+ char *next_dst;
+
+ #ifdef TEST
+
+ if (image -> bytes_per_line != 4 * image -> width)
+ {
+ fprintf(stderr, "******BitmapCompressData: PANIC! Image as [%d] bytes per line with expected [%d].\n",
+ image -> bytes_per_line, 4 * image -> width);
+
+ return NULL;
+ }
+
+ #endif
+
+ *size = image -> width * image -> height * 3;
+
+ data = Xmalloc(*size);
+
+ if (data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******BitmapCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
+ *size);
+ #endif
+
+ *size = image -> bytes_per_line * image -> height;
+
+ return image -> data;
+ }
+
+ next_src = image -> data;
+ next_dst = data;
+
+ if (image -> byte_order == LSBFirst)
+ {
+ while (next_src < image -> data +
+ image -> bytes_per_line * image -> height)
+ {
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+
+ next_src++;
+ }
+ }
+ else
+ {
+ while (next_src < image -> data +
+ image -> bytes_per_line * image -> height)
+ {
+ next_src++;
+
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ *next_dst++ = *next_src++;
+ }
+ }
+
+ return data;
+ }
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h
new file mode 100644
index 000000000..e45836d11
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Bitmap.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Bitmap_H
+#define Bitmap_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *BitmapCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Bitmap_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c
new file mode 100644
index 000000000..7a6d81b6b
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.c
@@ -0,0 +1,349 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "os.h"
+
+#include "Compext.h"
+
+#include "Clean.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+int CleanXYImage(XImage *image)
+{
+ int i, j, k, plane;
+
+ int bitsToClean = (image -> bytes_per_line << 3) - image -> width - image -> xoffset;
+
+ unsigned int bytesToClean = bitsToClean >> 3;
+
+ bitsToClean &= 7;
+
+ for (k = 0; k < image -> depth; k++)
+ {
+ plane = k * (image -> bytes_per_line * image -> height);
+
+ for (i = 1; i <= image -> height; i++)
+ {
+ if (image -> byte_order == image -> bitmap_bit_order)
+ {
+ for (j = 1; j <= bytesToClean; j++)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+ else
+ {
+ for (j = bytesToClean; j >= 1; j--)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+
+ if (image -> bitmap_bit_order == MSBFirst)
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff << bitsToClean;
+ }
+ else
+ {
+ image -> data[plane + i * (image -> bytes_per_line) - j] &= 0xff >> bitsToClean;
+ }
+ }
+ }
+
+ return 1;
+}
+
+int CleanZImage(XImage *image)
+{
+ unsigned int bytesToClean;
+ unsigned int j;
+ unsigned int imageLength;
+
+ #ifdef TEST
+ fprintf(stderr, "*****CleanZImage: Going to clean image of [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ switch (image -> bits_per_pixel)
+ {
+ case 32:
+ {
+ /*
+ * The caller should pay attention at extracting
+ * the alpha channel prior to cleaning the image.
+ * Cleaning an image which is carrying the alpha
+ * channel will result in the image being treated
+ * as fully transparent.
+ */
+
+ register int i;
+
+ bytesToClean = image -> bytes_per_line * image -> height;
+
+ #ifdef DEBUG
+ fprintf(stderr, "*****CleanZImage: Cleaning [%d] bytes with bits per pixel [%d] "
+ "width [%d] bytes per line [%d] height [%d].\n", bytesToClean,
+ image -> bits_per_pixel, image -> width, image ->
+ bytes_per_line, image -> height);
+ #endif
+
+ if (image -> byte_order == LSBFirst)
+ {
+ for (i = 3; i < bytesToClean; i += 4)
+ {
+ ((unsigned char *) image -> data)[i] = 0x00;
+ }
+ }
+ else
+ {
+ for (i = 0; i < bytesToClean; i += 4)
+ {
+ ((unsigned char *) image -> data)[i] = 0x00;
+ }
+ }
+
+ break;
+ }
+ case 24:
+ case 15:
+ case 16:
+ case 8:
+ {
+ register int i, j;
+
+ bytesToClean = image -> bytes_per_line -
+ ((image -> width * image -> bits_per_pixel) >> 3);
+
+ for (i = 1; i <= image -> height; i++)
+ {
+ for (j = bytesToClean; j > 0; j--)
+ {
+ ((unsigned char *) image -> data)[(i * image -> bytes_per_line) - j] = 0x00;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "*****CleanZImage: PANIC! Cannot clean image with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+ }
+ }
+
+ /*
+ * Clean the padding bytes at the real
+ * end of the buffer.
+ */
+
+ imageLength = image -> bytes_per_line * image -> height;
+
+ bytesToClean = imageLength % 4;
+
+ for (j = 0; j < bytesToClean; j++)
+ {
+ ((unsigned char *)image -> data)[(imageLength + j)] = 0x00;
+ }
+
+ return 1;
+}
+
+/*
+ * Copy a clean version of src_image into dst_image.
+ * This code is not taking care of the image format.
+ * The agent doesn't use it and you have to consider
+ * it unsupported.
+ */
+
+int CopyAndCleanImage(XImage *src_image, XImage *dst_image)
+{
+ register long data_size;
+ register int i;
+
+ data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
+
+ #ifdef WARNING
+ fprintf(stderr, "******CleanImage: WARNING! Function called with image of [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ switch (src_image -> bits_per_pixel)
+ {
+ case 32:
+ {
+ unsigned int mask;
+
+ if (src_image -> byte_order == MSBFirst)
+ {
+ mask = 0xffffff00;
+ }
+ else
+ {
+ mask = 0x00ffffff;
+ }
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i] & mask;
+ }
+
+ break;
+ }
+
+ case 24:
+ {
+ unsigned int bytes_to_clean;
+
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *)dst_image -> data)[i] = ((unsigned int *)src_image -> data)[i];
+ }
+
+ bytes_to_clean = dst_image -> bytes_per_line - ((dst_image -> width *
+ dst_image -> bits_per_pixel) >> 3);
+
+ if (bytes_to_clean)
+ {
+ register unsigned int mask = 0xffffffff;
+ register int line_size;
+ register int i;
+
+ line_size = dst_image -> bytes_per_line >> 2;
+
+ if (dst_image -> byte_order == MSBFirst)
+ {
+ mask = mask << (bytes_to_clean << 3);
+ }
+ else
+ {
+ mask = mask >> (bytes_to_clean << 3);
+ }
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((unsigned char *)dst_image -> data)[(++i * line_size) -1] &= mask;
+ }
+ }
+
+ break;
+ }
+
+ case 15:
+ case 16:
+ {
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
+ }
+
+ if (src_image -> width & 0x00000001)
+ {
+ int card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= 0x0000ffff;
+ }
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ unsigned int mask = 0x00000000;
+
+ switch (dst_image -> width % 4)
+ {
+ case 3:
+ {
+ mask = 0x00ffffff;
+
+ break;
+ }
+ case 2:
+ {
+ mask = 0x0000ffff;
+
+ break;
+ }
+ case 1:
+ {
+ mask = 0x000000ff;
+
+ break;
+ }
+ default:
+ {
+ /*
+ * Nothing to clean.
+ */
+
+ break;
+ }
+ }
+
+ for (i = 0; i < data_size; i++)
+ {
+ ((unsigned int *) dst_image -> data)[i] = ((unsigned int *) src_image -> data)[i];
+ }
+
+ if (mask)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height; i++)
+ {
+ ((unsigned int *) dst_image -> data)[(++i * card32_per_line) -1] &= mask;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******CleanImage: PANIC! Cannot clean image of [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+ }
+
+ return 1;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h
new file mode 100644
index 000000000..510af1dfb
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Clean.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Clean_H
+#define Clean_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/Xlib.h>
+
+int CleanXYImage(XImage *image);
+int CleanZImage(XImage *image);
+
+int CopyAndCleanImage(XImage *src_image, XImage *dst_image);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Clean_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c
new file mode 100644
index 000000000..6b025542d
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.c
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Colormap.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define COLORMAP_COMPRESSION_LEVEL 4
+#define COLORMAP_COMPRESSION_THRESHOLD 32
+#define COLORMAP_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int colormapCompressionLevel = COLORMAP_COMPRESSION_LEVEL;
+static int colormapCompressionThreshold = COLORMAP_COMPRESSION_THRESHOLD;
+static int colormapCompressionStrategy = COLORMAP_COMPRESSION_STRATEGY;
+
+char *ColormapCompressData(const char *data, unsigned int size, unsigned int *compressed_size)
+{
+ return ZCompressData(data, size, colormapCompressionThreshold, colormapCompressionLevel,
+ colormapCompressionStrategy, compressed_size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h
new file mode 100644
index 000000000..e30f4fdab
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Colormap.h
@@ -0,0 +1,45 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef ColormapComp_H
+#define ColormapComp_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *ColormapCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ColormapComp_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c
new file mode 100644
index 000000000..8a53da376
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.c
@@ -0,0 +1,4778 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#undef _XSERVER64
+
+#include <sys/socket.h>
+
+#ifndef __sun
+#include <strings.h>
+#endif
+
+#include "dix.h"
+#include "os.h"
+
+/*
+ * Needed to enable definition of the callback
+ * functions.
+ */
+
+#define NX_TRANS_SOCKET
+
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xutil.h>
+#include <nx-X11/Xlibint.h>
+
+#include "Compext.h"
+
+#include <nx/NX.h>
+#include <nx/NXproto.h>
+#include <nx/NXpack.h>
+#include <nx/MD5.h>
+
+#include "Clean.h"
+#include "Mask.h"
+#include "Colormap.h"
+#include "Alpha.h"
+#include "Bitmap.h"
+#include "Jpeg.h"
+#include "Png.h"
+#include "Rgb.h"
+#include "Rle.h"
+#include "Z.h"
+
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+#undef DUMP
+
+/*
+ * Maximum number of colors allowed in
+ * Png encoding.
+ */
+
+#define NB_COLOR_MAX 256
+
+/*
+ * Dummy error handlers used internally to catch
+ * Xlib failures in replies.
+ */
+
+static int _NXInternalReplyErrorFunction(Display *dpy, XErrorEvent *error);
+
+static void _NXInternalLostSequenceFunction(Display *dpy, unsigned long newseq,
+ unsigned long lastseq, unsigned int type);
+
+/*
+ * Resource ids that can be requested by
+ * the client for use in split or unpack
+ * operations.
+ */
+
+static unsigned char _NXSplitResources[NXNumberOfResources];
+static unsigned char _NXUnpackResources[NXNumberOfResources];
+
+static Display *_NXDisplayInitialized = NULL;
+
+/*
+ * Used in asynchronous handling of
+ * GetImage replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ unsigned long mask;
+ int format;
+ int width;
+ int height;
+ _XAsyncHandler *handler;
+ XImage *image;
+} _NXCollectImageState;
+
+static _NXCollectImageState *_NXCollectedImages[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GetProperty replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ Window window;
+ Atom property;
+ Atom type;
+ int format;
+ unsigned long items;
+ unsigned long after;
+ _XAsyncHandler *handler;
+ char *data;
+} _NXCollectPropertyState;
+
+static _NXCollectPropertyState *_NXCollectedProperties[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GrabPointer replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ int status;
+ _XAsyncHandler *handler;
+} _NXCollectGrabPointerState;
+
+static _NXCollectGrabPointerState *_NXCollectedGrabPointers[NXNumberOfResources];
+
+/*
+ * Used in asynchronous handling of
+ * GetInputFocus replies.
+ */
+
+typedef struct
+{
+ unsigned long sequence;
+ unsigned int resource;
+ Window focus;
+ int revert_to;
+ _XAsyncHandler *handler;
+} _NXCollectInputFocusState;
+
+static _NXCollectInputFocusState *_NXCollectedInputFocuses[NXNumberOfResources];
+
+/*
+ * Used by functions handling cache of
+ * packed images.
+ */
+
+#define MD5_LENGTH 16
+
+typedef struct
+{
+ md5_byte_t *md5;
+ XImage *image;
+ unsigned int method;
+} _NXImageCacheEntry;
+
+int NXImageCacheSize = 0;
+int NXImageCacheHits = 0;
+int NXImageCacheOps = 0;
+
+_NXImageCacheEntry *NXImageCache = NULL;
+
+#ifdef DUMP
+
+void _NXCacheDump(const char *label);
+
+void _NXDumpData(const unsigned char *buffer, unsigned int size);
+
+#endif
+
+/*
+ * From X11/PutImage.c.
+ *
+ * Cancel a GetReq operation, before doing
+ * _XSend or Data.
+ */
+
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define UnGetReq(name)\
+ dpy->bufptr -= SIZEOF(x##name##Req);\
+ dpy->request--
+#else
+#define UnGetReq(name)\
+ dpy->bufptr -= SIZEOF(x/**/name/**/Req);\
+ dpy->request--
+#endif
+
+#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP)
+#define UnGetEmptyReq()\
+ dpy->bufptr -= 4;\
+ dpy->request--
+#else
+#define UnGetEmptyReq(name)\
+ dpy->bufptr -= 4;\
+ dpy->request--
+#endif
+
+/*
+ * From X11/ImUtil.c.
+ */
+
+extern int _XGetBitsPerPixel(Display *dpy, int depth);
+extern int _XGetScanlinePad(Display *dpy, int depth);
+
+#define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & \
+ ~(long)((pad) - 1))
+
+static unsigned int DepthOnes(unsigned long mask)
+{
+ register unsigned long y;
+
+ y = (mask >> 1) &033333333333;
+ y = mask - y - ((y >>1) & 033333333333);
+ return ((unsigned int) (((y + (y >> 3)) &
+ 030707070707) % 077));
+}
+
+#define CanMaskImage(image, mask) \
+\
+(image -> format == ZPixmap && mask != NULL && \
+ (image -> depth == 32 || image -> depth == 24 || \
+ (image -> depth == 16 && (image -> red_mask == 0xf800 && \
+ image -> green_mask == 0x7e0 && image -> blue_mask == 0x1f))))
+
+#define ShouldMaskImage(image, mask) (mask -> color_mask != 0xff)
+
+/*
+ * Initialize and reset the internal structures.
+ */
+
+extern int _NXInternalInitResources(Display *dpy);
+extern int _NXInternalResetResources(Display *dpy);
+extern int _NXInternalInitEncoders(Display *dpy);
+extern int _NXInternalResetEncoders(Display *dpy);
+
+int NXInitDisplay(Display *dpy)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXInitDisplay: Called for display at [%p].\n", (void *) dpy);
+ #endif
+
+ if (_NXDisplayInitialized == NULL)
+ {
+ _NXInternalInitResources(dpy);
+
+ _NXInternalInitEncoders(dpy);
+
+ _NXDisplayInitialized = dpy;
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInitDisplay: WARNING! Internal structures already initialized.\n");
+ #endif
+
+ return 0;
+}
+
+int NXResetDisplay(Display *dpy)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXResetDisplay: Called for display at [%p].\n", (void *) dpy);
+ #endif
+
+ if (_NXDisplayInitialized != NULL)
+ {
+ _NXInternalResetResources(dpy);
+
+ _NXInternalResetEncoders(dpy);
+
+ _NXDisplayInitialized = NULL;
+
+ return 1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXResetDisplay: WARNING! Internal structures already reset.\n");
+ #endif
+
+ return 0;
+}
+
+int _NXInternalInitResources(Display *dpy)
+{
+ return _NXInternalResetResources(dpy);
+}
+
+int _NXInternalResetResources(Display *dpy)
+{
+ int i;
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: Clearing all the internal structures.\n");
+ #endif
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ _NXSplitResources[i] = 0;
+ _NXUnpackResources[i] = 0;
+
+ if (_NXCollectedImages[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect image data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedImages[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedImages[i] -> handler);
+
+ Xfree(_NXCollectedImages[i] -> handler);
+ }
+
+ if (_NXCollectedImages[i] -> image != NULL)
+ {
+ XDestroyImage(_NXCollectedImages[i] -> image);
+ }
+
+ Xfree(_NXCollectedImages[i]);
+
+ _NXCollectedImages[i] = NULL;
+ }
+
+ if (_NXCollectedProperties[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect property data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedProperties[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedProperties[i] -> handler);
+
+ Xfree(_NXCollectedProperties[i] -> handler);
+ }
+
+ if (_NXCollectedProperties[i] -> data != NULL)
+ {
+ Xfree(_NXCollectedProperties[i] -> data);
+ }
+
+ Xfree(_NXCollectedProperties[i]);
+
+ _NXCollectedProperties[i] = NULL;
+ }
+
+ if (_NXCollectedGrabPointers[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing grab pointer data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedGrabPointers[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedGrabPointers[i] -> handler);
+
+ Xfree(_NXCollectedGrabPointers[i] -> handler);
+ }
+
+ Xfree(_NXCollectedGrabPointers[i]);
+
+ _NXCollectedGrabPointers[i] = NULL;
+ }
+
+ if (_NXCollectedInputFocuses[i] != NULL)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalResetResources: WARNING! Clearing collect input focus data "
+ "for resource [%d].\n", i);
+ #endif
+
+ if (_NXCollectedInputFocuses[i] -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, _NXCollectedInputFocuses[i] -> handler);
+
+ Xfree(_NXCollectedInputFocuses[i] -> handler);
+ }
+
+ Xfree(_NXCollectedInputFocuses[i]);
+
+ _NXCollectedInputFocuses[i] = NULL;
+ }
+ }
+
+ return 1;
+}
+
+int _NXInternalInitEncoders(Display *dpy)
+{
+ ZInitEncoder();
+
+ return 1;
+}
+
+int _NXInternalResetEncoders(Display *dpy)
+{
+ ZResetEncoder();
+
+ return 1;
+}
+
+int NXSetDisplayPolicy(Display *dpy, int policy)
+{
+ if (policy == NXPolicyImmediate)
+ {
+ return NXTransPolicy(NX_FD_ANY, NX_POLICY_IMMEDIATE);
+ }
+ else
+ {
+ return NXTransPolicy(NX_FD_ANY, NX_POLICY_DEFERRED);
+ }
+}
+
+int NXSetDisplayBuffer(Display *dpy, int size)
+{
+ /*
+ * This is not multi-thread safe, so,
+ * if you have threads, be sure that
+ * they are stopped.
+ */
+
+ char *buffer;
+
+ XFlush(dpy);
+
+ if (dpy -> bufmax - size == dpy -> buffer)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBuffer: Nothing to do with buffer size matching.\n");
+ #endif
+
+ return 1;
+ }
+ else if (dpy -> bufptr != dpy -> buffer)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetDisplayBuffer: PANIC! The display buffer is not empty.\n");
+ #endif
+
+ return -1;
+ }
+ else if ((buffer = Xcalloc(1, size)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetDisplayBuffer: PANIC! Can't allocate [%d] bytes for the buffer.\n",
+ size);
+ #endif
+
+ return -1;
+ }
+
+ if (dpy -> buffer != NULL)
+ {
+ Xfree(dpy -> buffer);
+ }
+
+ dpy -> buffer = buffer;
+ dpy -> bufptr = dpy -> buffer;
+ dpy -> bufmax = dpy -> bufptr + size;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBuffer: Set the display output buffer size to [%d].\n",
+ size);
+ #endif
+
+ return 1;
+}
+
+/*
+ * If set, the Popen() function in the X server
+ * wil remove the LD_LIBRARY_PATH variable from
+ * the environment before calling the execl()
+ * function on the child process.
+ */
+
+int NXUnsetLibraryPath(int value)
+{
+ int previous = _NXUnsetLibraryPath;
+
+ _NXUnsetLibraryPath = value;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXUnsetLibraryPath: Set the flag to [%d] with previous value [%d].\n",
+ value, previous);
+ #endif
+
+ return previous;
+}
+
+/*
+ * If set, the Xlib I/O error handler will simply
+ * return, instead of quitting the program. This
+ * leaves to the application the responsibility
+ * of checking the state of the XlibDisplayIOEr-
+ * ror flag.
+ */
+
+int NXHandleDisplayError(int value)
+{
+ int previous = _NXHandleDisplayError;
+
+ _NXHandleDisplayError = value;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXHandleDisplayError: Set the flag to [%d] with previous value [%d].\n",
+ value, previous);
+ #endif
+
+ return previous;
+}
+
+/*
+ * Shutdown the display descriptor and force Xlib
+ * to set the I/O error flag.
+ */
+
+Bool NXForceDisplayError(Display *dpy)
+{
+ if (dpy != NULL)
+ {
+ NXTransClose(dpy -> fd);
+
+ if (!(dpy -> flags & XlibDisplayIOError))
+ {
+ shutdown(dpy -> fd, SHUT_RDWR);
+
+ _XIOError(dpy);
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Check if the display has become invalid. Similarly
+ * to the modified Xlib, we call the predicate funct-
+ * ion with the value of the XlibDisplayIOError flag
+ * only if the I/O error was not encountered already.
+ * The application can use this function to query the
+ * XlibDisplayIOError flag because Xlib doesn't expose
+ * the internals of the display structure to the appli-
+ * cation.
+ */
+
+int NXDisplayError(Display *dpy)
+{
+ if (dpy != NULL)
+ {
+ return (_XGetIOError(dpy) ||
+ (_NXDisplayErrorFunction != NULL &&
+ (*_NXDisplayErrorFunction)(dpy, _XGetIOError(dpy))));
+ }
+
+ return 1;
+}
+
+/*
+ * Various queries related to the state of the
+ * display connection.
+ */
+
+int NXDisplayReadable(Display *dpy)
+{
+ int result;
+ int readable;
+
+ result = NXTransReadable(dpy -> fd, &readable);
+
+ if (result == 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXDisplayReadable: Returning [%d] bytes readable from fd [%d].\n",
+ readable, dpy -> fd);
+ #endif
+
+ return readable;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXDisplayReadable: WARNING! Error detected on display fd [%d].\n",
+ dpy -> fd);
+ #endif
+
+ return -1;
+}
+
+int NXDisplayFlushable(Display *dpy)
+{
+ #ifdef DEBUG
+
+ int flushable;
+
+ flushable = NXTransFlushable(dpy -> fd) +
+ (dpy -> bufptr - dpy -> buffer);
+
+ fprintf(stderr, "******NXDisplayFlushable: Returning [%d+%d=%d] bytes flushable "
+ "to fd [%d].\n", (int) (dpy -> bufptr - dpy -> buffer),
+ (int) (flushable - (dpy -> bufptr - dpy -> buffer)),
+ flushable, dpy -> fd);
+
+ return flushable;
+
+ #else
+
+ return NXTransFlushable(dpy -> fd) + (dpy -> bufptr - dpy -> buffer);
+
+ #endif
+}
+
+int NXDisplayCongestion(Display *dpy)
+{
+ #ifdef DEBUG
+
+ int congestion = NXTransCongestion(dpy -> fd);
+
+ fprintf(stderr, "******NXDisplayCongestion: Returning [%d] as congestion level for fd [%d].\n",
+ congestion, dpy -> fd);
+
+ return congestion;
+
+ #else
+
+ return NXTransCongestion(dpy -> fd);
+
+ #endif
+}
+
+int NXFlushDisplay(Display *dpy, int what)
+{
+ if (!(dpy -> flags & XlibDisplayWriting) &&
+ dpy -> bufptr - dpy -> buffer > 0)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFlushDisplay: Writing with [%d] bytes in the buffer.\n",
+ (int) (dpy -> bufptr - dpy -> buffer));
+ #endif
+
+ XFlush(dpy);
+ }
+
+ if (what == NXFlushBuffer)
+ {
+ return 0;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFlushDisplay: Flushing with [%d] bytes in the NX transport.\n",
+ NXDisplayFlushable(dpy));
+ #endif
+
+ return NXTransFlush(dpy -> fd);
+}
+
+NXDisplayErrorPredicate NXSetDisplayErrorPredicate(NXDisplayErrorPredicate predicate)
+{
+ NXDisplayErrorPredicate previous = _NXDisplayErrorFunction;
+
+ _NXDisplayErrorFunction = predicate;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayErrorPredicate: Set the predicate to [%p] with previous value [%p].\n",
+ predicate, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayBlockHandler NXSetDisplayBlockHandler(NXDisplayBlockHandler handler)
+{
+ NXDisplayBlockHandler previous = _NXDisplayBlockFunction;
+
+ _NXDisplayBlockFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayBlockHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayWriteHandler NXSetDisplayWriteHandler(NXDisplayWriteHandler handler)
+{
+ NXDisplayWriteHandler previous = _NXDisplayWriteFunction;
+
+ _NXDisplayWriteFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayWriteHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayFlushHandler NXSetDisplayFlushHandler(NXDisplayFlushHandler handler, Display *display)
+{
+ NXDisplayFlushHandler previous = _NXDisplayFlushFunction;
+
+ _NXDisplayFlushFunction = handler;
+
+ NXTransHandler(NX_FD_ANY, NX_HANDLER_FLUSH,
+ (void (*)(void *, int)) handler, (void *) display);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayFlushHandler: Set the handler to [%p] with display [%p] "
+ "and previous value [%p].\n", handler, display, previous);
+ #endif
+
+ return previous;
+}
+
+NXDisplayStatisticsHandler NXSetDisplayStatisticsHandler(NXDisplayStatisticsHandler handler, char **buffer)
+{
+ NXDisplayStatisticsHandler previous = _NXDisplayStatisticsFunction;
+
+ _NXDisplayStatisticsFunction = handler;
+
+ /*
+ * Propagate the handler.
+ */
+
+ NXTransHandler(NX_FD_ANY, NX_HANDLER_STATISTICS,
+ (void (*)(void *, int)) handler, (void *) buffer);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetDisplayStatisticsHandler: Set the handler to [%p] with buffer pointer [%p] "
+ "and previous value [%p].\n", handler, buffer, previous);
+ #endif
+
+ return previous;
+}
+
+NXLostSequenceHandler NXSetLostSequenceHandler(NXLostSequenceHandler handler)
+{
+ NXLostSequenceHandler previous = _NXLostSequenceFunction;
+
+ _NXLostSequenceFunction = handler;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetLostSequenceHandler: Set the handler to [%p] with previous value [%p].\n",
+ handler, previous);
+ #endif
+
+ return previous;
+}
+
+int _NXInternalReplyErrorFunction(Display *dpy, XErrorEvent *error)
+{
+ #ifdef TEST
+ fprintf(stderr, "******_NXInternalReplyErrorFunction: Internal error handler called.\n");
+ #endif
+
+ return 0;
+}
+
+void _NXInternalLostSequenceFunction(Display *dpy, unsigned long newseq,
+ unsigned long lastseq, unsigned int type)
+{
+ #ifdef TEST
+
+ fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Sequence lost with new "
+ "sequence %ld last request %ld.\n", newseq, dpy -> request);
+
+ /*
+ * TODO: Reply or event info must be implemented.
+ *
+ * fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Expected event or reply "
+ * "was %ld with sequence %ld.\n", (long) rep -> type, (long) rep -> sequenceNumber);
+ */
+
+ fprintf(stderr, "******_NXInternalLostSequenceFunction: WARNING! Last sequence read "
+ "was %ld display request is %ld.\n", lastseq & 0xffff, dpy -> request & 0xffff);
+
+ #endif
+}
+
+Status NXGetControlParameters(Display *dpy, unsigned int *link_type, unsigned int *local_major,
+ unsigned int *local_minor, unsigned int *local_patch,
+ unsigned int *remote_major, unsigned int *remote_minor,
+ unsigned int *remote_patch, int *split_timeout, int *motion_timeout,
+ int *split_mode, int *split_size, unsigned int *pack_method,
+ unsigned int *pack_quality, int *data_level, int *stream_level,
+ int *delta_level, unsigned int *load_cache,
+ unsigned int *save_cache, unsigned int *startup_cache)
+{
+ xNXGetControlParametersReply rep;
+
+ _X_UNUSED register xReq *req;
+
+ LockDisplay(dpy);
+
+ GetEmptyReq(NXGetControlParameters, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Sending message opcode [%d].\n",
+ X_NXGetControlParameters);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == xFalse)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetControlParameters: Got reply with link type [%u].\n", rep.linkType);
+
+ fprintf(stderr, "******NXGetControlParameters: Local protocol major [%u] minor [%u] patch [%u].\n",
+ rep.localMajor, rep.localMinor, rep.localPatch);
+
+ fprintf(stderr, "******NXGetControlParameters: Remote protocol major [%u] minor [%u] patch [%u].\n",
+ rep.remoteMajor, rep.remoteMinor, rep.remotePatch);
+
+ fprintf(stderr, "******NXGetControlParameters: Split timeout [%d] motion timeout [%d].\n",
+ (int) rep.splitTimeout, (int) rep.motionTimeout);
+
+ fprintf(stderr, "******NXGetControlParameters: Split mode [%d] split size [%d].\n",
+ (int) rep.splitMode, (int) rep.splitSize);
+
+ fprintf(stderr, "******NXGetControlParameters: Preferred pack method [%d] pack quality [%d].\n",
+ (int) rep.packMethod, (int) rep.packQuality);
+
+ fprintf(stderr, "******NXGetControlParameters: Data level [%d] stream level [%d] delta level [%d].\n",
+ rep.dataLevel, rep.streamLevel, rep.deltaLevel);
+ #endif
+
+ *link_type = rep.linkType;
+
+ *local_major = rep.localMajor;
+ *local_minor = rep.localMinor;
+ *local_patch = rep.localPatch;
+
+ *remote_major = rep.remoteMajor;
+ *remote_minor = rep.remoteMinor;
+ *remote_patch = rep.remotePatch;
+
+ *split_timeout = rep.splitTimeout;
+ *motion_timeout = rep.motionTimeout;
+
+ *split_mode = rep.splitMode;
+ *split_size = rep.splitSize;
+
+ *pack_method = rep.packMethod;
+ *pack_quality = rep.packQuality;
+
+ *data_level = rep.dataLevel;
+ *stream_level = rep.streamLevel;
+ *delta_level = rep.deltaLevel;
+
+ *load_cache = rep.loadCache;
+ *save_cache = rep.saveCache;
+ *startup_cache = rep.startupCache;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ /*
+ * Install our internal out-of-sync handler.
+ */
+
+ _NXLostSequenceFunction = _NXInternalLostSequenceFunction;
+
+ return 1;
+}
+
+/*
+ * Which unpack methods are supported by the
+ * remote proxy?
+ */
+
+Status NXGetUnpackParameters(Display *dpy, unsigned int *entries, unsigned char supported_methods[])
+{
+ register xNXGetUnpackParametersReq *req;
+
+ xNXGetUnpackParametersReply rep;
+
+ register unsigned n;
+
+ #ifdef TEST
+ register unsigned i;
+ #endif
+
+ if (*entries < NXNumberOfPackMethods)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Requested only [%d] entries while they should be [%d].\n",
+ *entries, NXNumberOfPackMethods);
+ #endif
+
+ return 0;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(NXGetUnpackParameters, req);
+
+ req -> entries = *entries;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Sending message opcode [%d] with [%d] requested entries.\n",
+ X_NXGetUnpackParameters, *entries);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == xFalse || rep.length == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ if ((n = rep.length << 2) > *entries)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Got [%d] bytes of reply data while they should be [%d].\n",
+ n, *entries);
+ #endif
+
+ _XEatData(dpy, (unsigned long) n);
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ *entries = n;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetUnpackParameters: Reading [%d] bytes of reply data.\n", n);
+ #endif
+
+ _XReadPad(dpy, (char *) supported_methods, n);
+
+ #ifdef TEST
+
+ fprintf(stderr, "******NXGetUnpackParameters: Got reply with methods: ");
+
+ for (i = 0; i < n; i++)
+ {
+ if (supported_methods[i] != 0)
+ {
+ fprintf(stderr, "[%d]", i);
+ }
+ }
+
+ fprintf(stderr, ".\n");
+
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Query and enable the MIT-SHM support between the
+ * proxy and the X server. The 'enable' flags must be
+ * true if shared memory PutImages and PutPackedImages
+ * are desired. On return the flags will say if support
+ * has been successfully enabled.
+ *
+ * Note that the the client part is not useful and not
+ * implemented. The size of the segment is chosen by
+ * the proxy. The main purpose of the message is to
+ * reserve the XID that will be used by the remote.
+ */
+
+Status NXGetShmemParameters(Display *dpy, unsigned int *enable_client,
+ unsigned int *enable_server, unsigned int *client_segment,
+ unsigned int *server_segment, unsigned int *client_size,
+ unsigned int *server_size)
+{
+ register xNXGetShmemParametersReq *req;
+
+ register int stage;
+
+ xNXGetShmemParametersReply rep;
+
+ /*
+ * Save the previous handler.
+ */
+
+ int (*handler)(Display *, XErrorEvent *) = _XErrorFunction;
+
+ *client_segment = 0;
+ *server_segment = 0;
+
+ if (*enable_client)
+ {
+ *client_segment = XAllocID(dpy);
+ }
+
+ if (*enable_server)
+ {
+ *server_segment = XAllocID(dpy);
+ }
+
+ LockDisplay(dpy);
+
+ _XErrorFunction = _NXInternalReplyErrorFunction;
+
+ for (stage = 0; stage < 3; stage++)
+ {
+ GetReq(NXGetShmemParameters, req);
+
+ req -> stage = stage;
+
+ req -> enableClient = (*enable_client != 0 ? 1 : 0);
+ req -> enableServer = (*enable_server != 0 ? 1 : 0);
+
+ req -> clientSegment = *client_segment;
+ req -> serverSegment = *server_segment;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Sending message opcode [%d] at stage [%d].\n",
+ X_NXGetShmemParameters, stage);
+ #endif
+
+ #ifdef TEST
+
+ if (stage == 0)
+ {
+ fprintf(stderr, "******NXGetShmemParameters: Enable client is [%u] enable server is [%u].\n",
+ *enable_client, *enable_server);
+
+ fprintf(stderr, "******NXGetShmemParameters: Client segment is [%u] server segment is [%u].\n",
+ *client_segment, *server_segment);
+ }
+
+ #endif
+
+ /*
+ * There isn't X server reply in the second stage.
+ * The procedure followed at X server side is:
+ *
+ * Stage 0: Send X_QueryExtension and masquerade
+ * the reply.
+ *
+ * Stage 1: Allocate the shared memory and send
+ * X_ShmAttach to the X server.
+ *
+ * Stage 2: Send X_GetInputFocus and masquerade
+ * the reply.
+ *
+ * The last message is used to force a reply and
+ * collect any X error caused by a failure in the
+ * shared memory initialization.
+ */
+
+ if (stage != 1)
+ {
+ /*
+ * We are only interested in the final reply.
+ */
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xTrue) == xFalse)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Error receiving reply.\n");
+ #endif
+
+ _XErrorFunction = handler;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+ }
+ }
+
+ /*
+ * Return the settings to client.
+ */
+
+ *enable_client = rep.clientEnabled;
+ *enable_server = rep.serverEnabled;
+
+ *client_size = rep.clientSize;
+ *server_size = rep.serverSize;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetShmemParameters: Got final reply with enabled client [%u] and server [%u].\n",
+ *enable_client, *enable_server);
+
+ fprintf(stderr, "******NXGetShmemParameters: Client segment size [%u] server segment size [%u].\n",
+ *client_size, *server_size);
+ #endif
+
+ _XErrorFunction = handler;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Get the path to the font server that can be used by the X
+ * server to tunnel the font connections across the NX link.
+ * The path actually represents the TCP port where the proxy
+ * on the NX client side is listening. The agent can tempora-
+ * rily enable the tunneling when it needs a font that is not
+ * available on the client, for example when the session is
+ * migrated from a different X server.
+ *
+ * Note that it is not advisable to use the font server chan-
+ * nel for other purposes than restoring a font that is found
+ * missing at the time the session is migrated to a different
+ * display. This is because the agent implements a caching of
+ * the list of fonts supported by the client as it needs to
+ * advertise only the fonts that can be opened at both sides.
+ */
+
+Status NXGetFontParameters(Display *dpy, unsigned int path_length, char path_data[])
+{
+ _X_UNUSED register xNXGetFontParametersReq *req;
+
+ xNXGetFontParametersReply rep;
+
+ register unsigned n;
+
+ #ifdef TEST
+ register unsigned i;
+ #endif
+
+ if (path_length < 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: No room to store the reply.\n");
+ #endif
+
+ return 0;
+ }
+
+ *path_data = '\0';
+
+ LockDisplay(dpy);
+
+ GetReq(NXGetFontParameters, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Sending message opcode [%d].\n",
+ X_NXGetFontParameters);
+ #endif
+
+ if (_XReply(dpy, (xReply *) &rep, 0, xFalse) == xFalse || rep.length == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Error receiving reply.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ if ((n = rep.length << 2) > path_length)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Got [%d] bytes of reply data with only room for [%d].\n",
+ n, path_length);
+ #endif
+
+ _XEatData(dpy, (unsigned long) n);
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Reading [%d] bytes of reply data.\n", n);
+ #endif
+
+ _XReadPad(dpy, (char *) path_data, n);
+
+ /*
+ * Check if the string can be fully
+ * contained by the buffer.
+ */
+
+ if (*path_data > path_length - 1)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXGetFontParameters: Inconsistent length in the returned string.\n");
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 0;
+ }
+
+ #ifdef TEST
+
+ fprintf(stderr, "******NXGetFontParameters: Got font path of [%d] bytes and value [",
+ (int) *path_data);
+
+ for (i = 0; i < *path_data; i++)
+ {
+ fprintf(stderr, "%c", *(path_data + i + 1));
+ }
+
+ fprintf(stderr, "].\n");
+
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+unsigned int NXAllocSplit(Display *dpy, unsigned int resource)
+{
+ if (resource == NXAnyResource)
+ {
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ if (_NXSplitResources[resource] == 0)
+ {
+ _NXSplitResources[resource] = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocSplit: Reserved resource [%u].\n",
+ resource);
+ #endif
+
+ return resource;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocSplit: WARNING! Resource limit exausted.\n");
+ #endif
+
+ return NXNoResource;
+ }
+ else if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ if (_NXSplitResources[resource] == 0)
+ {
+ fprintf(stderr, "******NXAllocSplit: Reserved requested resource [%u].\n",
+ resource);
+ }
+ else
+ {
+ fprintf(stderr, "******NXAllocSplit: Requested resource [%u] already reserved.\n",
+ resource);
+ }
+
+ #endif
+
+ _NXSplitResources[resource] = 1;
+ }
+
+ #ifdef PANIC
+ fprintf(stderr, "******NXAllocSplit: PANIC! Can't reserve requested resource [%u].\n",
+ resource);
+ #endif
+
+ return NXNoResource;
+}
+
+/*
+ * Tell the proxy to split the next messages.
+ */
+
+int NXStartSplit(Display *dpy, unsigned int resource, unsigned int mode)
+{
+ register xNXStartSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXStartSplit, req);
+
+ req -> resource = resource;
+ req -> mode = mode;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXStartSplit: Sending opcode [%d] with resource [%d] mode [%d].\n",
+ X_NXStartSplit, resource, mode);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Send the closure of the split sequence and
+ * tell the proxy to send the results.
+ */
+
+int NXEndSplit(Display *dpy, unsigned int resource)
+{
+ register xNXEndSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXEndSplit, req);
+
+ req -> resource = resource;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXEndSplit: Sending opcode [%d] with resource [%d].\n",
+ X_NXStartSplit, resource);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * This message must be sent whenever the proxy notifies
+ * the client of the completion of a split. If the 'pro-
+ * pagate' field is 0, the proxy will not send the ori-
+ * ginal request to the X server, but will only free the
+ * internal state.
+ */
+
+int NXCommitSplit(Display *dpy, unsigned int resource, unsigned int propagate,
+ unsigned char request, unsigned int position)
+{
+ register xNXCommitSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXCommitSplit, req);
+
+ req -> resource = resource;
+ req -> propagate = propagate;
+ req -> request = request;
+ req -> position = position;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCommitSplit: Sending opcode [%d] with resource [%d] propagate [%d] "
+ "request [%d] position [%d].\n", X_NXCommitSplit, resource,
+ propagate, request, position);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXAbortSplit(Display *dpy, unsigned int resource)
+{
+ register xNXAbortSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXAbortSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAbortSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXAbortSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXFinishSplit(Display *dpy, unsigned int resource)
+{
+ register xNXFinishSplitReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXFinishSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFinishSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFinishSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXFreeSplit(Display *dpy, unsigned int resource)
+{
+ register xNXFreeSplitReq *req;
+
+ if (_NXSplitResources[resource] != 0)
+ {
+ LockDisplay(dpy);
+
+ GetReq(NXFreeSplit, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeSplit: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFreeSplit, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeSplit: Making the resource [%u] newly available.\n",
+ resource);
+ #endif
+
+ _NXSplitResources[resource] = 0;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******NXFreeSplit: Nothing to do for resource [%u].\n",
+ resource);
+ }
+ #endif
+
+ return 1;
+}
+
+/*
+ * Tell to remote proxy to discard expose events
+ * of one or more types.
+ */
+
+int NXSetExposeParameters(Display *dpy, int expose, int graphics_expose, int no_expose)
+{
+ register xNXSetExposeParametersReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetExposeParameters, req);
+
+ req -> expose = expose;
+ req -> graphicsExpose = graphics_expose;
+ req -> noExpose = no_expose;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetExposeParameters: Sending message opcode [%d] with flags [%d][%d][%d].\n",
+ X_NXSetExposeParameters, req -> expose, req -> graphicsExpose, req -> noExpose);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Tell to the local proxy how to handle the next requests.
+ */
+
+int NXSetCacheParameters(Display *dpy, int enable_cache, int enable_split,
+ int enable_save, int enable_load)
+{
+ register xNXSetCacheParametersReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetCacheParameters, req);
+
+ req -> enableCache = enable_cache;
+ req -> enableSplit = enable_split;
+ req -> enableSave = enable_save;
+ req -> enableLoad = enable_load;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetCacheParameters: Sending message opcode [%d] with "
+ "flags [%d][%d][%d][%d].\n", X_NXSetCacheParameters, req -> enableCache,
+ req -> enableSplit, req -> enableSave, req -> enableLoad);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+unsigned int NXAllocUnpack(Display *dpy, unsigned int resource)
+{
+ if (resource == NXAnyResource)
+ {
+ for (resource = 0; resource < NXNumberOfResources; resource++)
+ {
+ if (_NXUnpackResources[resource] == 0)
+ {
+ _NXUnpackResources[resource] = 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocUnpack: Reserved resource [%u].\n",
+ resource);
+ #endif
+
+ return resource;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXAllocUnpack: WARNING! Resource limit exausted.\n");
+ #endif
+
+ return NXNoResource;
+ }
+ else if (resource >= 0 && resource < NXNumberOfResources)
+ {
+ #ifdef TEST
+
+ if (_NXUnpackResources[resource] == 0)
+ {
+ fprintf(stderr, "******NXAllocUnpack: Reserved requested resource [%u].\n",
+ resource);
+ }
+ else
+ {
+ fprintf(stderr, "******NXAllocUnpack: Requested resource [%u] already reserved.\n",
+ resource);
+ }
+
+ #endif
+
+ _NXUnpackResources[resource] = 1;
+ }
+
+ #ifdef PANIC
+ fprintf(stderr, "******NXAllocUnpack: PANIC! Can't reserve requested resource [%u].\n",
+ resource);
+ #endif
+
+ return NXNoResource;
+}
+
+int NXSetUnpackGeometry(Display *dpy, unsigned int resource, Visual *visual)
+{
+ register xNXSetUnpackGeometryReq *req;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackGeometry, req);
+
+ req -> resource = resource;
+
+ req -> depth1Bpp = _XGetBitsPerPixel(dpy, 1);
+ req -> depth4Bpp = _XGetBitsPerPixel(dpy, 4);
+ req -> depth8Bpp = _XGetBitsPerPixel(dpy, 8);
+ req -> depth16Bpp = _XGetBitsPerPixel(dpy, 16);
+ req -> depth24Bpp = _XGetBitsPerPixel(dpy, 24);
+ req -> depth32Bpp = _XGetBitsPerPixel(dpy, 32);
+
+ if (visual != NULL)
+ {
+ req -> redMask = visual -> red_mask;
+ req -> greenMask = visual -> green_mask;
+ req -> blueMask = visual -> blue_mask;
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackGeometry: PANIC! Can't set the geometry without a visual.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackGeometry);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackGeometry: Resource [%u] Depth/Bpp [1/%d][4/%d][8/%d]"
+ "[16/%d][24/%d][32/%d].\n", resource, req -> depth1Bpp, req -> depth4Bpp,
+ req -> depth8Bpp, req -> depth16Bpp, req -> depth24Bpp, req -> depth32Bpp);
+
+ fprintf(stderr, "******NXSetUnpackGeometry: red [0x%x] green [0x%x] blue [0x%x].\n",
+ (unsigned) req -> redMask, (unsigned) req -> greenMask, (unsigned) req -> blueMask);
+ #endif
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Store a colormap table on the remote side.
+ * The colormap can then be used to unpack
+ * an image.
+ */
+
+int NXSetUnpackColormap(Display *dpy, unsigned int resource, unsigned int method,
+ unsigned int entries, const char *data, unsigned int data_length)
+{
+ register xNXSetUnpackColormapReq *req;
+
+ register int dst_data_length;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackColormap, req);
+
+ req -> resource = resource;
+ req -> method = method;
+
+ req -> srcLength = data_length;
+ req -> dstLength = entries << 2;
+
+ dst_data_length = ROUNDUP(data_length, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackColormap: Resource [%u] data size [%u] destination "
+ "data size [%u].\n", resource, data_length, dst_data_length);
+ #endif
+
+ if (data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, data, data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, data, data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Store data of the alpha blending channel
+ * that will be combined with the next image
+ * to be unpacked.
+ */
+
+int NXSetUnpackAlpha(Display *dpy, unsigned int resource, unsigned int method,
+ unsigned int entries, const char *data, unsigned int data_length)
+{
+ register xNXSetUnpackAlphaReq *req;
+
+ register unsigned int dst_data_length;
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackAlpha, req);
+
+ req -> resource = resource;
+ req -> method = method;
+
+ req -> srcLength = data_length;
+ req -> dstLength = entries;
+
+ dst_data_length = ROUNDUP(data_length, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackAlpha: Resource [%u] data size [%u] destination data size [%u].\n",
+ resource, data_length, dst_data_length);
+ #endif
+
+ if (data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, data, data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, data, data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Compatibility versions to be used when
+ * connected to a 1.X.X proxy.
+ */
+
+/*
+ * These are for compatibility with the 1.X.X
+ * versions.
+ */
+
+#define sz_xNXSetUnpackColormapCompatReq 8
+
+typedef struct _NXSetUnpackColormapCompatReq {
+ CARD8 reqType;
+ CARD8 resource;
+ CARD16 length B16;
+ CARD32 entries B32;
+} xNXSetUnpackColormapCompatReq;
+
+#define X_NXSetUnpackColormapCompat X_NXSetUnpackColormap
+
+int NXSetUnpackColormapCompat(Display *dpy, unsigned int resource,
+ unsigned int entries, const char *data)
+{
+ register xNXSetUnpackColormapCompatReq *req;
+
+ register char *dst_data;
+
+ register int dst_data_length;
+
+ #ifdef DUMP
+
+ int i;
+
+ #endif
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackColormapCompat, req);
+
+ req -> resource = resource;
+ req -> entries = entries;
+
+ dst_data_length = entries << 2;
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackColormapCompat: Resource [%u] number of entries [%u] "
+ "destination data size [%u].\n", resource, entries, dst_data_length);
+ #endif
+
+ if (entries > 0)
+ {
+ if ((dpy -> bufptr + dst_data_length) <= dpy -> bufmax)
+ {
+ dst_data = dpy -> bufptr;
+ }
+ else
+ {
+ if ((dst_data = _XAllocScratch(dpy, dst_data_length)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackColormapCompat: PANIC! Cannot allocate memory.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackColormapCompat);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+ }
+
+ memcpy(dst_data, data, entries << 2);
+
+ #ifdef DUMP
+
+ fprintf(stderr, "******NXSetUnpackColormapCompat: Dumping colormap entries:\n");
+
+ for (i = 0; i < entries; i++)
+ {
+ fprintf(stderr, "******NXSetUnpackColormapCompat: [%d] -> [0x%x].\n",
+ i, *((int *) (dst_data + (i * 4))));
+ }
+
+ #endif
+
+ if (dst_data == dpy -> bufptr)
+ {
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ _XSend(dpy, dst_data, dst_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+#define sz_xNXSetUnpackAlphaCompatReq 8
+
+typedef struct _NXSetUnpackAlphaCompatReq {
+ CARD8 reqType;
+ CARD8 resource;
+ CARD16 length B16;
+ CARD32 entries B32;
+} xNXSetUnpackAlphaCompatReq;
+
+#define X_NXSetUnpackAlphaCompat X_NXSetUnpackAlpha
+
+int NXSetUnpackAlphaCompat(Display *dpy, unsigned int resource,
+ unsigned int entries, const char *data)
+{
+ register xNXSetUnpackAlphaCompatReq *req;
+
+ register char *dst_data;
+
+ register unsigned int dst_data_length;
+
+ #ifdef DUMP
+
+ int i;
+
+ #endif
+
+ LockDisplay(dpy);
+
+ GetReq(NXSetUnpackAlphaCompat, req);
+
+ req -> resource = resource;
+ req -> entries = entries;
+
+ dst_data_length = ROUNDUP(entries, 4);
+
+ req -> length += (dst_data_length >> 2);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: Resource [%u] number of entries [%u] "
+ "destination data size [%u].\n", resource, entries, dst_data_length);
+ #endif
+
+ if (entries > 0)
+ {
+ if ((dpy -> bufptr + dst_data_length) <= dpy -> bufmax)
+ {
+ dst_data = dpy -> bufptr;
+ }
+ else
+ {
+ if ((dst_data = _XAllocScratch(dpy, dst_data_length)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: PANIC! Cannot allocate memory.\n");
+ #endif
+
+ UnGetReq(NXSetUnpackAlphaCompat);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+ }
+
+ memcpy(dst_data, data, entries);
+
+ if (dst_data_length != entries)
+ {
+ memset(dst_data + entries, 0, dst_data_length - entries);
+ }
+
+ #ifdef DUMP
+
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: Dumping alpha channel data:\n");
+
+ for (i = 0; i < dst_data_length; i++)
+ {
+ fprintf(stderr, "******NXSetUnpackAlphaCompat: [%d] -> [0x%02x].\n",
+ i, ((unsigned int) *(dst_data + i)) & 0xff);
+ }
+
+ #endif
+
+ if (dst_data == dpy -> bufptr)
+ {
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ _XSend(dpy, dst_data, dst_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+/*
+ * Free any geometry, colormap and alpha channel
+ * data stored by the remote proxy to unpack the
+ * image. Resource, as usual, must be a value
+ * between 0 and 255.
+ */
+
+int NXFreeUnpack(Display *dpy, unsigned int resource)
+{
+ register xNXFreeUnpackReq *req;
+
+ if (_NXUnpackResources[resource] != 0)
+ {
+ LockDisplay(dpy);
+
+ GetReq(NXFreeUnpack, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeUnpack: Sending message opcode [%d] with resource [%u].\n",
+ X_NXFreeUnpack, resource);
+ #endif
+
+ req -> resource = resource;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ #ifdef TEST
+ fprintf(stderr, "******NXFreeUnpack: Making the resource [%u] newly available.\n",
+ resource);
+ #endif
+
+ _NXUnpackResources[resource] = 0;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******NXFreeUnpack: Nothing to do for resource [%u].\n",
+ resource);
+ }
+ #endif
+
+ return 1;
+}
+
+/*
+ * Wrapper of XCreateImage(). Note that we use offset
+ * field of XImage to store size of source image in
+ * packed format. Note also that method is currently
+ * not stored in the NXignored.
+ */
+
+NXPackedImage *NXCreatePackedImage(Display *dpy, Visual *visual, unsigned int method,
+ unsigned int depth, int format, char *data,
+ int data_length, unsigned int width,
+ unsigned int height, int bitmap_pad,
+ int bytes_per_line)
+{
+ XImage* image;
+
+ image = XCreateImage(dpy, visual, depth, format, 0, data,
+ width, height, bitmap_pad, bytes_per_line);
+
+ if (image != NULL)
+ {
+ image -> xoffset = data_length;
+ }
+
+ return (NXPackedImage *) image;
+}
+
+/*
+ * Wrapper of XDestroyImage().
+ */
+
+int NXDestroyPackedImage(NXPackedImage *image)
+{
+ return XDestroyImage((XImage *) image);
+}
+
+/*
+ * Clean the image data directly in the current buffer.
+ */
+
+int NXCleanImage(XImage *image)
+{
+ #ifdef TEST
+ fprintf(stderr, "******NXCleanImage: Cleaning image with format [%d] depth [%d] "
+ "bits per pixel [%d].\n", image -> format, image -> depth,
+ image -> bits_per_pixel);
+ #endif
+
+ if (image -> format == ZPixmap)
+ {
+ if (image -> depth == 1)
+ {
+ return CleanXYImage(image);
+ }
+ else
+ {
+ return CleanZImage(image);
+ }
+ }
+ else
+ {
+ return CleanXYImage(image);
+ }
+}
+
+NXPackedImage *NXPackImage(Display *dpy, XImage *src_image, unsigned int method)
+{
+ XImage *dst_image;
+
+ const ColorMask *mask;
+
+ unsigned int dst_data_size;
+ unsigned int dst_packed_data_size;
+
+ unsigned int dst_bits_per_pixel;
+ unsigned int dst_packed_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Going to pack a new image with method [%d].\n",
+ method);
+ #endif
+
+ /*
+ * Get the mask out of the method and
+ * check if the visual is supported by
+ * the color reduction algorithm.
+ */
+
+ mask = MethodColorMask(method);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: WARNING! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return NULL;
+ }
+ else if (CanMaskImage(src_image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ src_image -> format, src_image -> depth, src_image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXPackImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ src_image -> red_mask, src_image -> green_mask, src_image -> blue_mask);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Create a destination image from
+ * source and apply the color mask.
+ */
+
+ if ((dst_image = (XImage *) Xmalloc(sizeof(XImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Source width [%d], bytes per line [%d] with depth [%d].\n",
+ src_image -> width, src_image -> bytes_per_line, src_image -> depth);
+ #endif
+
+ dst_data_size = src_image -> bytes_per_line * src_image -> height;
+
+ dst_image -> data = Xmalloc(dst_data_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Cannot allocate [%d] bytes for masked image data.\n",
+ dst_data_size);
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * If the pixel resulting from the mask
+ * needs more bits than available, then
+ * just clean the padding bits in the
+ * image.
+ */
+
+ dst_bits_per_pixel = dst_image -> bits_per_pixel;
+ dst_packed_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Destination depth [%d], bits per pixel [%d], packed bits per pixel [%d].\n",
+ dst_image -> depth, dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ if (dst_packed_bits_per_pixel > dst_bits_per_pixel ||
+ ShouldMaskImage(src_image, mask) == 0)
+ {
+ /*
+ * Should use the same data for source
+ * and destination to avoid the memcpy.
+ */
+
+ if (CopyAndCleanImage(src_image, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to clean the image.\n");
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+ }
+ else if (MaskImage(mask, src_image, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to apply the color mask.\n");
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Let's pack the same pixels in fewer bytes.
+ * Note that we save a new memory allocation
+ * by using the same image as source and des-
+ * tination. This means that PackImage() must
+ * be able to handle ovelapping areas.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Plain bits per pixel [%d], data size [%d].\n",
+ dst_bits_per_pixel, dst_data_size);
+ #endif
+
+ dst_packed_data_size = dst_data_size * dst_packed_bits_per_pixel /
+ dst_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPackImage: Packed bits per pixel [%d], data size [%d].\n",
+ dst_packed_bits_per_pixel, dst_packed_data_size);
+ #endif
+
+ if (PackImage(method, dst_data_size, dst_image,
+ dst_packed_data_size, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXPackImage: PANIC! Failed to pack image from [%d] to [%d] bits per pixel.\n",
+ dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ Xfree(dst_image -> data);
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Save data size in xoffset field
+ * to comply with NX packed images.
+ */
+
+ dst_image -> xoffset = dst_packed_data_size;
+
+ return dst_image;
+}
+
+/*
+ * NXInPlacePackImage creates a NXPackedImage
+ * from a XImage, sharing the same data buffer.
+ * Is up to the caller to free the data buffer
+ * only once.
+ */
+
+XImage *NXInPlacePackImage(Display *dpy, XImage *src_image, unsigned int method)
+{
+ XImage *dst_image;
+
+ const ColorMask *mask;
+
+ unsigned int dst_data_size;
+ unsigned int dst_packed_data_size;
+
+ unsigned int dst_bits_per_pixel;
+ unsigned int dst_packed_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Going to pack a new image with method [%d].\n",
+ method);
+ #endif
+
+ /*
+ * Get mask out of method and check if
+ * visual is supported by current color
+ * reduction algorithm.
+ */
+
+ mask = MethodColorMask(method);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: WARNING! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return NULL;
+ }
+ else if (CanMaskImage(src_image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ src_image -> format, src_image -> depth, src_image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ src_image -> red_mask, src_image -> green_mask, src_image -> blue_mask);
+ #endif
+ return NULL;
+ }
+
+ /*
+ * Create a destination image from
+ * source and apply the color mask.
+ */
+
+ if ((dst_image = (XImage *) Xmalloc(sizeof(XImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Source width [%d], bytes per line [%d] with depth [%d].\n",
+ src_image -> width, src_image -> bytes_per_line, src_image -> depth);
+ #endif
+
+ dst_data_size = src_image -> bytes_per_line * src_image -> height;
+
+ dst_image -> data = src_image -> data;
+
+ /*
+ * If pixel resulting from mask needs
+ * more bits than available, then just
+ * clean the pad bits in image.
+ */
+
+ dst_bits_per_pixel = dst_image -> bits_per_pixel;
+ dst_packed_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Destination depth [%d], bits per pixel [%d], packed bits per pixel [%d].\n",
+ dst_image -> depth, dst_bits_per_pixel, dst_packed_bits_per_pixel);
+ #endif
+
+ if (dst_packed_bits_per_pixel > dst_bits_per_pixel ||
+ ShouldMaskImage(src_image, mask) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Just clean image packed_bits_per_pixel[%d], bits_per_pixel[%d].\n",
+ dst_packed_bits_per_pixel, dst_bits_per_pixel);
+ #endif
+
+ if (NXCleanImage(dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Failed to clean the image.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+ }
+ else if (MaskInPlaceImage(mask, dst_image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXInPlacePackImage: PANIC! Failed to apply the color mask.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Let's pack the same pixels in fewer bytes.
+ * Note that we save a new memory allocation
+ * by using the same image as source and des-
+ * tination. This means that PackImage() must
+ * be able to handle ovelapping areas.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Plain bits per pixel [%d], data size [%d].\n",
+ dst_bits_per_pixel, dst_data_size);
+ #endif
+
+ dst_packed_data_size = dst_data_size * dst_packed_bits_per_pixel /
+ dst_bits_per_pixel;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXInPlacePackImage: Packed bits per pixel [%d], data size [%d].\n",
+ dst_packed_bits_per_pixel, dst_packed_data_size);
+ #endif
+
+ /*
+ * Save data size in xoffset field
+ * to comply with NX packed images.
+ */
+
+ dst_image -> xoffset = dst_packed_data_size;
+
+ return dst_image;
+}
+
+int NXPutPackedImage(Display *dpy, unsigned int resource, Drawable drawable,
+ void *gc, NXPackedImage *image, unsigned int method,
+ unsigned int depth, int src_x, int src_y, int dst_x,
+ int dst_y, unsigned int width, unsigned int height)
+{
+ register xNXPutPackedImageReq *req;
+
+ register unsigned int src_data_length;
+ register unsigned int dst_data_length;
+
+ LockDisplay(dpy);
+
+ FlushGC(dpy, (GC) gc);
+
+ GetReq(NXPutPackedImage, req);
+
+ req -> resource = resource;
+ req -> drawable = drawable;
+ req -> gc = ((GC) gc) -> gid;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Image resource [%d] drawable [%d] gc [%d].\n",
+ req -> resource, (int) req -> drawable, (int) req -> gc);
+ #endif
+
+ /*
+ * There is no leftPad field in request. We only
+ * support a leftPad of 0. Anyway, X imposes a
+ * leftPad of 0 in case of ZPixmap format.
+ */
+
+ req -> format = image -> format;
+
+ /*
+ * Source depth, as well as width and height,
+ * are taken from the image structure.
+ */
+
+ req -> srcDepth = image -> depth;
+
+ req -> srcX = src_x;
+ req -> srcY = src_y;
+
+ req -> srcWidth = image -> width;
+ req -> srcHeight = image -> height;
+
+ /*
+ * The destination depth is provided
+ * by the caller.
+ */
+
+ req -> dstDepth = depth;
+
+ req -> dstX = dst_x;
+ req -> dstY = dst_y;
+
+ req -> dstWidth = width;
+ req -> dstHeight = height;
+
+ req -> method = method;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Source image depth [%d] destination depth [%d] "
+ "method [%d].\n", req -> srcDepth, req -> dstDepth, req -> method);
+ #endif
+
+ /*
+ * Source data length is the size of image in packed format,
+ * as stored in xoffset field of XImage. Destination data
+ * size is calculated according to bytes per line of target
+ * image, so the caller must provide the right depth at the
+ * time XImage structure is created.
+ */
+
+ req -> srcLength = image -> xoffset;
+
+ if (image -> width == (int) width &&
+ image -> height == (int) height)
+ {
+ req -> dstLength = image -> bytes_per_line * image -> height;
+ }
+ else if (image -> format == ZPixmap)
+ {
+ req -> dstLength = ROUNDUP((image -> bits_per_pixel * width),
+ image -> bitmap_pad) * height >> 3;
+ }
+ else
+ {
+ req -> dstLength = ROUNDUP(width, image -> bitmap_pad) * height >> 3;
+ }
+
+ src_data_length = image -> xoffset;
+
+ dst_data_length = ROUNDUP(src_data_length, 4);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXPutPackedImage: Source data length [%d] request data length [%d].\n",
+ src_data_length, dst_data_length);
+ #endif
+
+ req -> length += (dst_data_length >> 2);
+
+ if (src_data_length > 0)
+ {
+ if (dpy -> bufptr + dst_data_length <= dpy -> bufmax)
+ {
+ /*
+ * Clean the padding bytes in the request.
+ */
+
+ *((int *) (dpy -> bufptr + dst_data_length - 4)) = 0x0;
+
+ memcpy(dpy -> bufptr, image -> data, src_data_length);
+
+ dpy -> bufptr += dst_data_length;
+ }
+ else
+ {
+ /*
+ * The _XSend() will pad the request for us.
+ */
+
+ _XSend(dpy, image -> data, src_data_length);
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXAllocColors(Display *dpy, Colormap colormap, unsigned int entries,
+ XColor screens_in_out[], Bool results_in_out[])
+{
+ Status result = 0;
+ xAllocColorReply rep;
+ register xAllocColorReq *req;
+
+ Bool alloc_error = False;
+
+ register unsigned int i;
+
+ LockDisplay(dpy);
+
+ for (i = 0; i < entries; i++)
+ {
+ GetReq(AllocColor, req);
+
+ req -> cmap = colormap;
+
+ req -> red = screens_in_out[i].red;
+ req -> green = screens_in_out[i].green;
+ req -> blue = screens_in_out[i].blue;
+ }
+
+ for (i = 0; i < entries; i++)
+ {
+ result = _XReply(dpy, (xReply *) &rep, 0, xTrue);
+
+ if (result)
+ {
+ screens_in_out[i].pixel = rep.pixel;
+
+ screens_in_out[i].red = rep.red;
+ screens_in_out[i].green = rep.green;
+ screens_in_out[i].blue = rep.blue;
+
+ results_in_out[i] = True;
+ }
+ else
+ {
+ results_in_out[i] = False;
+
+ alloc_error = True;
+ }
+ }
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return (alloc_error == False);
+}
+
+char *NXEncodeColormap(const char *src_data, unsigned int src_size, unsigned int *dst_size)
+{
+ return ColormapCompressData(src_data, src_size, dst_size);
+}
+
+char *NXEncodeAlpha(const char *src_data, unsigned int src_size, unsigned int *dst_size)
+{
+ return AlphaCompressData(src_data, src_size, dst_size);
+}
+
+NXPackedImage *NXEncodeRgb(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRgb: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = RgbCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRgb: PANIC! Rgb compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Rgb size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeRle(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRle: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = RleCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeRle: PANIC! Rle compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Rle size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeBitmap(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ unsigned int dst_size;
+
+ /*
+ * Create a new image structure as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeBitmap: PANIC! Cannot allocate [%d] bytes for the image.\n",
+ (int) sizeof(XImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = BitmapCompressData(src_image, &dst_size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeBitmap: PANIC! Bitmap compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the bitmap size in the xoffset field.
+ */
+
+ dst_image -> xoffset = dst_size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodeJpeg(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ int size;
+
+ /*
+ * Check if the bpp of the image is valid
+ * for the Jpeg compression.
+ */
+
+ if (src_image -> bits_per_pixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Invalid bpp for Jpeg compression [%d]\n.",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Create the destination image as a copy
+ * of the source.
+ */
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Cannot allocate [%d] bytes for the Jpeg image.\n",
+ (int) sizeof(NXPackedImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = JpegCompressData(src_image, quality, &size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodeJpeg: PANIC! Jpeg compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Jpeg size in the xoffset field.
+ */
+
+ dst_image -> xoffset = size;
+
+ return dst_image;
+}
+
+NXPackedImage *NXEncodePng(XImage *src_image, unsigned int method, unsigned int quality)
+{
+ NXPackedImage *dst_image = NULL;
+
+ int size;
+
+ /*
+ * Check if the bpp of the image is valid
+ * for png compression.
+ */
+
+ if (src_image -> bits_per_pixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Invalid bpp for Png compression [%d].\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return NULL;
+ }
+
+ if ((dst_image = (NXPackedImage *) Xmalloc(sizeof(NXPackedImage))) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Cannot allocate [%d] bytes for the Png image.\n",
+ (int) sizeof(NXPackedImage));
+ #endif
+
+ return NULL;
+ }
+
+ *dst_image = *src_image;
+
+ dst_image -> data = PngCompressData(dst_image, &size);
+
+ if (dst_image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXEncodePng: PANIC! Png compression failed.\n");
+ #endif
+
+ Xfree(dst_image);
+
+ return NULL;
+ }
+
+ /*
+ * Store the Png size in the xoffset field.
+ */
+
+ dst_image -> xoffset = size;
+
+ return dst_image;
+}
+
+int NXEncodeColors(XImage *src_image, NXColorTable *color_table, int nb_max)
+{
+ int x, y, t, p;
+
+ long pixel;
+
+ /*
+ * We need a smarter way to extract
+ * the colors from the image and
+ * create a color table.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> width; x++)
+ {
+ for (y = 0; y < src_image -> height; y++)
+ {
+ pixel = XGetPixel(src_image, x, y);
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if ( color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+
+ p++;
+
+ break;
+ }
+ else if ((color_table[t].pixel) == pixel)
+ {
+ break;
+ }
+ }
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+
+ return p;
+}
+
+void NXMaskImage(XImage *image, unsigned int method)
+{
+ unsigned int maskMethod;
+
+ const ColorMask *mask;
+
+ /*
+ * Choose the correct mask method
+ */
+
+ switch(method)
+ {
+ case PACK_JPEG_8_COLORS:
+ case PACK_PNG_8_COLORS:
+ {
+ maskMethod = MASK_8_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_8_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_64_COLORS:
+ case PACK_PNG_64_COLORS:
+ {
+ maskMethod = MASK_64_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_64K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_256_COLORS:
+ case PACK_PNG_256_COLORS:
+ {
+ maskMethod = MASK_256_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_256_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_512_COLORS:
+ case PACK_PNG_512_COLORS:
+ {
+ maskMethod = MASK_512_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_512K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_4K_COLORS:
+ case PACK_PNG_4K_COLORS:
+ {
+ maskMethod = MASK_4K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_4K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_32K_COLORS:
+ case PACK_PNG_32K_COLORS:
+ {
+ maskMethod = MASK_32K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_32K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_64K_COLORS:
+ case PACK_PNG_64K_COLORS:
+ {
+ maskMethod = MASK_64K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_64K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_256K_COLORS:
+ case PACK_PNG_256K_COLORS:
+ {
+ maskMethod = MASK_256K_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_256K_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_2M_COLORS:
+ case PACK_PNG_2M_COLORS:
+ {
+ maskMethod = MASK_2M_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_2M_COLORS\n");
+ #endif
+
+ break;
+ }
+ case PACK_JPEG_16M_COLORS:
+ case PACK_PNG_16M_COLORS:
+ {
+ maskMethod = MASK_16M_COLORS;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXMaskImage: Method is MASK_16M_COLORS\n");
+ #endif
+
+ break;
+ }
+ default:
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Cannot find mask method for pack method [%d]\n",
+ method);
+ #endif
+
+ return;
+ }
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******NXMaskImage: packMethod[%d] => maskMethod[%d]\n",
+ method, maskMethod);
+ #endif
+
+ /*
+ * Get mask out of method and check if
+ * visual is supported by current color
+ * reduction algorithm.
+ */
+
+ mask = MethodColorMask(maskMethod);
+
+ if (mask == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! No mask to apply for pack method [%d].\n",
+ method);
+ #endif
+
+ return;
+ }
+ else if (CanMaskImage(image, mask) == 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Invalid source with format [%d] depth [%d] bits per pixel [%d].\n",
+ image -> format, image -> depth, image -> bits_per_pixel);
+
+ fprintf(stderr, "******NXMaskImage: PANIC! Visual colormask is red 0x%lx green 0x%lx blue 0x%lx.\n",
+ image -> red_mask, image -> green_mask, image -> blue_mask);
+ #endif
+
+ return;
+ }
+
+ /*
+ * Calling ShouldMaskImage you get 0 in the case
+ * of MASK_256_COLORS and MASK_64K_COLORS, which
+ * means that the image should not be masked.
+ */
+
+ if (ShouldMaskImage(image, mask) == 0)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******NXMaskImage: the image will not be masked\n");
+ #endif
+ }
+ else
+ {
+ if (MaskInPlaceImage(mask, image) <= 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXMaskImage: PANIC! Failed to apply the color mask in place.\n");
+ #endif
+ }
+ }
+}
+
+/*
+ * The display parameter is ignored.
+ */
+
+void NXInitCache(Display *dpy, int entries)
+{
+ if (NXImageCache != NULL && NXImageCacheSize == entries)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Nothing to do with image cache at [%p] and [%d] entries.\n",
+ NXImageCache, NXImageCacheSize);
+ #endif
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Initializing the cache with [%d] entries.\n",
+ entries);
+ #endif
+
+ NXImageCacheSize = 0;
+
+ if (NXImageCache != NULL)
+ {
+ Xfree(NXImageCache);
+
+ NXImageCache = NULL;
+ }
+
+ if (entries > 0)
+ {
+ NXImageCache = Xmalloc(entries * sizeof(_NXImageCacheEntry));
+
+ if (NXImageCache != NULL)
+ {
+ memset(NXImageCache, 0, entries * sizeof(_NXImageCacheEntry));
+
+ NXImageCacheSize = entries;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXInitCache: Image cache initialized with [%d] entries.\n", entries);
+ #endif
+ }
+ }
+}
+
+#ifdef DUMP
+
+void _NXCacheDump(const char *label)
+{
+ char s[MD5_LENGTH * 2 + 1];
+
+ int i;
+ int j;
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: Dumping the content of image cache:\n", label);
+ #endif
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image == NULL)
+ {
+ break;
+ }
+
+ for (j = 0; j < MD5_LENGTH; j++)
+ {
+ sprintf(s + (j * 2), "%02X", ((unsigned char *) NXImageCache[i].md5)[j]);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "%s: [%d][%s].\n", label, i, s);
+ #endif
+ }
+}
+
+#endif
+
+XImage *NXCacheFindImage(NXPackedImage *src_image, unsigned int *method, unsigned char **md5)
+{
+ md5_state_t new_state;
+ md5_byte_t *new_md5;
+ unsigned int data_size, i;
+
+ if (NXImageCache == NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ * Will return the allocated checksum
+ * if the image is not found.
+ */
+
+ *md5 = NULL;
+
+ if ((new_md5 = Xmalloc(MD5_LENGTH)) == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCacheFindImage: Can't allocate memory for the checksum.\n");
+ #endif
+
+ return NULL;
+ }
+
+ data_size = (src_image -> bytes_per_line * src_image -> height);
+
+ md5_init(&new_state);
+
+ md5_append(&new_state, (unsigned char *) &src_image -> width, sizeof(int));
+ md5_append(&new_state, (unsigned char *) &src_image -> height, sizeof(int));
+
+ md5_append(&new_state, (unsigned char *) src_image -> data, data_size);
+
+ md5_finish(&new_state, new_md5);
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image != NULL)
+ {
+ if (memcmp(NXImageCache[i].md5, new_md5, MD5_LENGTH) == 0)
+ {
+ _NXImageCacheEntry found;
+
+ found.image = NXImageCache[i].image;
+ found.method = NXImageCache[i].method;
+ found.md5 = NXImageCache[i].md5;
+
+ *method = found.method;
+
+ NXImageCacheHits++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheFindImage: Found at position [%d] with hits [%d] and [%d] packs.\n",
+ i, NXImageCacheHits, NXImageCacheOps);
+ #endif
+
+ Xfree(new_md5);
+
+ /*
+ * Move the images down one slot, from
+ * the head of the list, and place the
+ * image just found at top.
+ */
+
+ if (i > 16)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheFindImage: Moving the image at the head of the list.\n");
+ #endif
+
+ memmove(&NXImageCache[1], &NXImageCache[0], (i * sizeof(_NXImageCacheEntry)));
+
+ NXImageCache[0].image = found.image;
+ NXImageCache[0].method = found.method;
+ NXImageCache[0].md5 = found.md5;
+
+ #ifdef DUMP
+
+ _NXCacheDump("******NXCacheFindImage");
+
+ #endif
+ }
+
+ /*
+ * Return the checksum and image
+ * structure allocated in cache.
+ */
+
+ *md5 = found.md5;
+
+ return found.image;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ *md5 = new_md5;
+
+ return NULL;
+}
+
+/*
+ * Add a packed image to the cache. A new image
+ * structure is allocated and copied, data and
+ * checksum are inherited from the passed image.
+ */
+
+int NXCacheAddImage(NXPackedImage *image, unsigned int method, unsigned char *md5)
+{
+ unsigned int i;
+
+ if (image == NULL || image -> data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCacheAddImage: PANIC! Invalid image passed to function.\n");
+ #endif
+
+ return -1;
+ }
+
+ i = (NXImageCacheOps < NXImageCacheSize) ? NXImageCacheOps : NXImageCacheSize;
+
+ if (NXImageCacheOps >= NXImageCacheSize)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheAddImage: Freeing up the oldest entry.\n");
+ #endif
+
+ i--;
+
+ Xfree(NXImageCache[NXImageCacheSize - 1].image -> data);
+ Xfree(NXImageCache[NXImageCacheSize - 1].image);
+ Xfree(NXImageCache[NXImageCacheSize - 1].md5);
+ }
+
+ if (i > 0)
+ {
+ memmove(&NXImageCache[1], &NXImageCache[0], i * sizeof(_NXImageCacheEntry));
+ }
+
+ NXImageCacheOps++;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXCacheAddImage: Going to add new image with data size [%d].\n",
+ image -> xoffset);
+ #endif
+
+ NXImageCache[0].image = image;
+ NXImageCache[0].method = method;
+ NXImageCache[0].md5 = md5;
+
+ #ifdef DUMP
+
+ _NXCacheDump("******NXCacheAddImage");
+
+ #endif
+
+ return 1;
+}
+
+/*
+ * The display parameter is ignored.
+ */
+
+void NXFreeCache(Display *dpy)
+{
+ int i;
+
+ if (NXImageCache == NULL)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFreeCache: Nothing to do with a null image cache.\n");
+ #endif
+
+ return;
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******NXFreeCache: Freeing the cache with [%d] entries.\n",
+ NXImageCacheSize);
+ #endif
+
+ for (i = 0; i < NXImageCacheSize; i++)
+ {
+ if (NXImageCache[i].image != NULL)
+ {
+ if (NXImageCache[i].image -> data != NULL)
+ {
+ Xfree(NXImageCache[i].image -> data);
+ }
+
+ Xfree(NXImageCache[i].image);
+
+ NXImageCache[i].image = NULL;
+ }
+
+ if (NXImageCache[i].md5 != NULL)
+ {
+ Xfree(NXImageCache[i].md5);
+
+ NXImageCache[i].md5 = NULL;
+ }
+ }
+
+ Xfree(NXImageCache);
+
+ NXImageCache = NULL;
+
+ NXImageCacheSize = 0;
+ NXImageCacheHits = 0;
+ NXImageCacheOps = 0;
+}
+
+static void _NXNotifyImage(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ /*
+ * Enqueue an event to tell client
+ * the result of GetImage.
+ */
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedImages[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectImageNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectImageHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectImageState *state;
+
+ register xGetImageReply *async_rep;
+
+ char *async_head;
+ char *async_data;
+
+ int async_size;
+
+ state = (_NXCollectImageState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to handle asynchronous GetImage reply.\n");
+ #endif
+
+ /*
+ * As even reply data is managed asynchronously,
+ * we can use state to get to vector and vector
+ * to get to handler. In this way, we can safely
+ * dequeue and free the handler itself.
+ */
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetImageReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetImageReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Got reply with depth [%d] visual [%d] size [%d].\n",
+ async_rep -> depth, (int) async_rep -> visual, (int) async_rep -> length << 2);
+ #endif
+
+ async_size = async_rep -> length << 2;
+
+ if (async_size > 0)
+ {
+ async_data = Xmalloc(async_size);
+
+ if (async_data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Going to get data with size [%d].\n",
+ async_size);
+ #endif
+
+ _XGetAsyncData(dpy, async_data, buf, len, SIZEOF(xGetImageReply), async_size, async_size);
+
+ /*
+ * From now on we can return True, as all
+ * data has been consumed from buffer.
+ */
+
+ if (state -> format == XYPixmap)
+ {
+ unsigned long depth = DepthOnes(state -> mask & (((unsigned long)0xFFFFFFFF) >>
+ (32 - async_rep -> depth)));
+
+ state -> image = XCreateImage(dpy, _XVIDtoVisual(dpy, async_rep -> visual),
+ depth, XYPixmap, 0, async_data, state -> width,
+ state -> height, dpy -> bitmap_pad, 0);
+ }
+ else
+ {
+ state -> image = XCreateImage(dpy, _XVIDtoVisual(dpy, async_rep -> visual),
+ async_rep -> depth, ZPixmap, 0, async_data, state -> width,
+ state -> height, _XGetScanlinePad(dpy, async_rep -> depth), 0);
+ }
+
+ if (state -> image == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectImageHandler: PANIC! Failed to create image for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, False);
+
+ _NXCollectedImages[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+ Xfree(async_data);
+
+ return True;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectImageHandler: Successfully stored image data for resource [%d].\n",
+ state -> resource);
+ #endif
+ }
+ #ifdef WARNING
+ else
+ {
+ fprintf(stderr, "******_NXCollectImageHandler: WARNING! Null image data stored for resource [%d].\n",
+ state -> resource);
+ }
+ #endif
+
+ _NXNotifyImage(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectImageResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedImages[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectImage(Display *dpy, unsigned int resource, Drawable drawable,
+ int src_x, int src_y, unsigned int width, unsigned int height,
+ unsigned long plane_mask, int format)
+{
+ register xGetImageReq *req;
+
+ _NXCollectImageState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedImages[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ if (state -> image != NULL)
+ {
+ XDestroyImage(state -> image);
+ }
+
+ Xfree(state);
+
+ _NXCollectedImages[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GetImage, req);
+
+ req -> format = format;
+ req -> drawable = drawable;
+ req -> x = src_x;
+ req -> y = src_y;
+ req -> width = width;
+ req -> height = height;
+ req -> planeMask = plane_mask;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectImage: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetImage, dpy -> request, resource);
+
+ fprintf(stderr, "******NXCollectImage: Format [%d] drawable [%d] src_x [%d] src_y [%d].\n",
+ req -> format, (int) req -> drawable, req -> x, req -> y);
+
+ fprintf(stderr, "******NXCollectImage: Width [%d] height [%d] plane_mask [%x].\n",
+ req -> width, req -> height, (int) req -> planeMask);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectImageState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectImage: PANIC! Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ UnGetReq(GetImage);
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> mask = plane_mask;
+ state -> format = format;
+ state -> width = width;
+ state -> height = height;
+ state -> image = NULL;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectImageHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedImages[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return 1;
+}
+
+int NXGetCollectedImage(Display *dpy, unsigned int resource, XImage **image)
+{
+ register _NXCollectImageState *state;
+
+ state = _NXCollectedImages[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedImage: PANIC! No image collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ _NXCollectedImages[resource] = NULL;
+
+ *image = state -> image;
+
+ Xfree(state);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedImage: Returning GetImage data for resource [%u].\n",
+ resource);
+ #endif
+
+ return 1;
+}
+
+static void _NXNotifyProperty(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ /*
+ * Enqueue an event to tell client
+ * the result of GetProperty.
+ */
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedProperties[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectPropertyNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectPropertyHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectPropertyState *state;
+
+ register xGetPropertyReply *async_rep;
+
+ char *async_head;
+ char *async_data;
+
+ int async_size;
+
+ state = (_NXCollectPropertyState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to handle asynchronous GetProperty reply.\n");
+ #endif
+
+ /*
+ * Reply data is managed asynchronously. We can
+ * use state to get to vector and vector to get
+ * to handler. In this way, we can dequeue and
+ * free the handler itself.
+ */
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetPropertyReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetPropertyReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Got reply with format [%d] type [%d] size [%d].\n",
+ async_rep -> format, (int) async_rep -> propertyType, (int) async_rep -> length << 2);
+
+ fprintf(stderr, "******_NXCollectPropertyHandler: Bytes after [%d] number of items [%d].\n",
+ (int) async_rep -> bytesAfter, (int) async_rep -> nItems);
+ #endif
+
+ state -> format = async_rep -> format;
+ state -> type = async_rep -> propertyType;
+ state -> items = async_rep -> nItems;
+ state -> after = async_rep -> bytesAfter;
+
+ async_size = async_rep -> length << 2;
+
+ if (async_size > 0)
+ {
+ async_data = Xmalloc(async_size);
+
+ if (async_data == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectPropertyHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, False);
+
+ _NXCollectedProperties[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Going to get data with size [%d].\n",
+ async_size);
+ #endif
+
+ _XGetAsyncData(dpy, async_data, buf, len, SIZEOF(xGetPropertyReply), async_size, async_size);
+
+ /*
+ * From now on we can return True, as all
+ * data has been consumed from buffer.
+ */
+
+ state -> data = async_data;
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectPropertyHandler: Successfully stored property data for resource [%d].\n",
+ state -> resource);
+ #endif
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******_NXCollectPropertyHandler: WARNING! Null property data stored for resource [%d].\n",
+ state -> resource);
+ }
+ #endif
+
+ _NXNotifyProperty(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectPropertyResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedProperties[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectProperty(Display *dpy, unsigned int resource, Window window, Atom property,
+ long long_offset, long long_length, Bool delete, Atom req_type)
+{
+ register xGetPropertyReq *req;
+
+ _NXCollectPropertyState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedProperties[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ if (state -> data != NULL)
+ {
+ Xfree(state -> data);
+ }
+
+ Xfree(state);
+
+ _NXCollectedProperties[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GetProperty, req);
+
+ req -> delete = delete;
+ req -> window = window;
+ req -> property = property;
+ req -> type = req_type;
+ req -> longOffset = long_offset;
+ req -> longLength = long_length;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectProperty: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetProperty, dpy -> request, resource);
+
+ fprintf(stderr, "******NXCollectProperty: Delete [%u] window [%d] property [%d] type [%d].\n",
+ req -> delete, (int) req -> window, (int) req -> property, (int) req -> type);
+
+ fprintf(stderr, "******NXCollectProperty: Long offset [%d] long length [%d].\n",
+ (int) req -> longOffset, (int) req -> longLength);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectPropertyState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectProperty: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetReq(GetProperty);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> window = window;
+ state -> property = property;
+ state -> type = 0;
+ state -> format = 0;
+ state -> items = 0;
+ state -> after = 0;
+ state -> data = NULL;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectPropertyHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedProperties[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedProperty(Display *dpy, unsigned int resource, Atom *actual_type_return,
+ int *actual_format_return, unsigned long *nitems_return,
+ unsigned long *bytes_after_return, unsigned char **data)
+{
+ register _NXCollectPropertyState *state;
+
+ state = _NXCollectedProperties[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedProperty: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *actual_type_return = state -> type;
+ *actual_format_return = state -> format;
+ *nitems_return = state -> items;
+ *bytes_after_return = state -> after;
+
+ *data = (unsigned char *) _NXCollectedProperties[resource] -> data;
+
+ Xfree(state);
+
+ _NXCollectedProperties[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedProperty: Returning GetProperty data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+static void _NXNotifyGrabPointer(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedGrabPointers[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectGrabPointerNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectGrabPointerHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectGrabPointerState *state;
+
+ register xGrabPointerReply *async_rep;
+
+ char *async_head;
+
+ int async_size;
+
+ state = (_NXCollectGrabPointerState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Going to handle asynchronous GrabPointer reply.\n");
+ #endif
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGrabPointerReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGrabPointerReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyGrabPointer(dpy, state -> resource, False);
+
+ _NXCollectedGrabPointers[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectGrabPointerHandler: Got reply with status [%d] size [%d].\n",
+ async_rep -> status, (int) async_rep -> length << 2);
+ #endif
+
+ state -> status = async_rep -> status;
+
+ _NXNotifyGrabPointer(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectGrabPointerResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedGrabPointers[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectGrabPointer(Display *dpy, unsigned int resource, Window grab_window, Bool owner_events,
+ unsigned int event_mask, int pointer_mode, int keyboard_mode,
+ Window confine_to, Cursor cursor, Time time)
+{
+ register xGrabPointerReq *req;
+
+ _NXCollectGrabPointerState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedGrabPointers[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ Xfree(state);
+
+ _NXCollectedGrabPointers[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetReq(GrabPointer, req);
+
+ req -> grabWindow = grab_window;
+ req -> ownerEvents = owner_events;
+ req -> eventMask = event_mask;
+ req -> pointerMode = pointer_mode;
+ req -> keyboardMode = keyboard_mode;
+ req -> confineTo = confine_to;
+ req -> cursor = cursor;
+ req -> time = time;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectGrabPointer: Sending message opcode [%d] sequence [%ld] "
+ "for resource [%d].\n", X_GrabPointer, dpy -> request, resource);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectGrabPointerState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectGrabPointer: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetReq(GrabPointer);
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> status = 0;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectGrabPointerHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedGrabPointers[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedGrabPointer(Display *dpy, unsigned int resource, int *status)
+{
+ register _NXCollectGrabPointerState *state;
+
+ state = _NXCollectedGrabPointers[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedGrabPointer: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *status = state -> status;
+
+ Xfree(state);
+
+ _NXCollectedGrabPointers[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedGrabPointer: Returning GrabPointer data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+static void _NXNotifyInputFocus(Display *dpy, int resource, Bool success)
+{
+ XEvent async_event;
+
+ async_event.type = ClientMessage;
+
+ async_event.xclient.serial = _NXCollectedInputFocuses[resource] -> sequence;
+
+ async_event.xclient.window = 0;
+ async_event.xclient.message_type = 0;
+ async_event.xclient.format = 32;
+
+ async_event.xclient.data.l[0] = NXCollectInputFocusNotify;
+ async_event.xclient.data.l[1] = resource;
+ async_event.xclient.data.l[2] = success;
+
+ XPutBackEvent(dpy, &async_event);
+}
+
+static Bool _NXCollectInputFocusHandler(Display *dpy, xReply *rep, char *buf,
+ int len, XPointer data)
+{
+ register _NXCollectInputFocusState *state;
+
+ register xGetInputFocusReply *async_rep;
+
+ char *async_head;
+
+ int async_size;
+
+ state = (_NXCollectInputFocusState *) data;
+
+ if ((rep -> generic.sequenceNumber % 65536) !=
+ ((int)(state -> sequence) % 65536))
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Unmatched sequence [%d] for opcode [%d] "
+ "with length [%d].\n", rep -> generic.sequenceNumber, rep -> generic.type,
+ (int) rep -> generic.length << 2);
+ #endif
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Going to handle asynchronous GetInputFocus reply.\n");
+ #endif
+
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+
+ state -> handler = NULL;
+
+ if (rep -> generic.type == X_Error)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Error received from X server for resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Matched request with sequence [%ld].\n",
+ state -> sequence);
+ #endif
+
+ async_size = SIZEOF(xGetInputFocusReply);
+
+ async_head = Xmalloc(async_size);
+
+ if (async_head == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectInputFocusHandler: PANIC! Failed to allocate memory with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Going to get reply with size [%d].\n",
+ (int) rep -> generic.length << 2);
+ #endif
+
+ async_rep = (xGetInputFocusReply *) _XGetAsyncReply(dpy, async_head, rep, buf, len, 0, False);
+
+ if (async_rep == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******_NXCollectInputFocusHandler: PANIC! Failed to get reply with resource [%d].\n",
+ state -> resource);
+ #endif
+
+ _NXNotifyInputFocus(dpy, state -> resource, False);
+
+ _NXCollectedInputFocuses[state -> resource] = NULL;
+
+ Xfree(state);
+
+ Xfree(async_head);
+
+ return False;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******_NXCollectInputFocusHandler: Got reply with focus [%d] revert to [%d] "
+ "size [%d].\n", (int) async_rep -> focus, (int) async_rep -> revertTo,
+ (int) async_rep -> length << 2);
+ #endif
+
+ state -> focus = async_rep -> focus;
+ state -> revert_to = async_rep -> revertTo;
+
+ _NXNotifyInputFocus(dpy, state -> resource, True);
+
+ Xfree(async_head);
+
+ return True;
+}
+
+int NXGetCollectInputFocusResource(Display *dpy)
+{
+ int i;
+
+ for (i = 0; i < NXNumberOfResources; i++)
+ {
+ if (_NXCollectedInputFocuses[i] == NULL)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+int NXCollectInputFocus(Display *dpy, unsigned int resource)
+{
+ _X_UNUSED register xReq *req;
+
+ _NXCollectInputFocusState *state;
+ _XAsyncHandler *handler;
+
+ if (resource >= NXNumberOfResources)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: PANIC! Provided resource [%u] is out of range.\n",
+ resource);
+ #endif
+
+ return -1;
+ }
+
+ state = _NXCollectedInputFocuses[resource];
+
+ if (state != NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: PANIC! Having to remove previous state for resource [%u].\n",
+ resource);
+ #endif
+
+ if (state -> handler != NULL)
+ {
+ DeqAsyncHandler(dpy, state -> handler);
+
+ Xfree(state -> handler);
+ }
+
+ Xfree(state);
+
+ _NXCollectedInputFocuses[resource] = NULL;
+ }
+
+ LockDisplay(dpy);
+
+ GetEmptyReq(GetInputFocus, req);
+
+ #ifdef TEST
+ fprintf(stderr, "******NXCollectInputFocus: Sending message opcode [%d] sequence [%ld] for resource [%d].\n",
+ X_GetInputFocus, dpy -> request, resource);
+ #endif
+
+ state = Xmalloc(sizeof(_NXCollectInputFocusState));
+ handler = Xmalloc(sizeof(_XAsyncHandler));
+
+ if (state == NULL || handler == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXCollectInputFocus: Failed to allocate memory with resource [%d].\n",
+ resource);
+ #endif
+
+ if (state != NULL)
+ {
+ Xfree(state);
+ }
+
+ if (handler != NULL)
+ {
+ Xfree(handler);
+ }
+
+ UnGetEmptyReq();
+
+ UnlockDisplay(dpy);
+
+ return -1;
+ }
+
+ state -> sequence = dpy -> request;
+ state -> resource = resource;
+ state -> focus = 0;
+ state -> revert_to = 0;
+
+ state -> handler = handler;
+
+ handler -> next = dpy -> async_handlers;
+ handler -> handler = _NXCollectInputFocusHandler;
+ handler -> data = (XPointer) state;
+ dpy -> async_handlers = handler;
+
+ _NXCollectedInputFocuses[resource] = state;
+
+ UnlockDisplay(dpy);
+
+ SyncHandle();
+
+ return True;
+}
+
+int NXGetCollectedInputFocus(Display *dpy, unsigned int resource,
+ Window *focus_return, int *revert_to_return)
+{
+ register _NXCollectInputFocusState *state;
+
+ state = _NXCollectedInputFocuses[resource];
+
+ if (state == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******NXGetCollectedInputFocus: PANIC! No data collected for resource [%u].\n",
+ resource);
+ #endif
+
+ return 0;
+ }
+
+ *focus_return = state -> focus;
+ *revert_to_return = state -> revert_to;
+
+ Xfree(state);
+
+ _NXCollectedInputFocuses[resource] = NULL;
+
+ #ifdef TEST
+ fprintf(stderr, "******NXGetCollectedInputFocus: Returning GetInputFocus data for resource [%u].\n",
+ resource);
+ #endif
+
+ return True;
+}
+
+#ifdef DUMP
+
+void _NXDumpData(const unsigned char *buffer, unsigned int size)
+{
+ if (buffer != NULL)
+ {
+ unsigned int i = 0;
+
+ unsigned int ii;
+
+ while (i < size)
+ {
+ fprintf(stderr, "[%d]\t", i);
+
+ for (ii = 0; i < size && ii < 8; i++, ii++)
+ {
+ fprintf(stderr, "%d\t", (unsigned int) (buffer[i]));
+ }
+
+ fprintf(stderr, "\n");
+ }
+ }
+}
+
+#endif
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h
new file mode 100644
index 000000000..ecd7d1e18
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Compext.h
@@ -0,0 +1,912 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef NXlib_H
+#define NXlib_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+
+#include <nx/NX.h>
+#include <nx/NXpack.h>
+#include <nx/NXproto.h>
+#include <nx/NXvars.h>
+
+/*
+ * All the NX code should use these.
+ */
+
+#define Xmalloc(size) malloc((size))
+#define Xfree(ptr) free((ptr))
+
+/*
+ * Maximum number of supported pack methods.
+ */
+
+#define NXNumberOfPackMethods 128
+
+/*
+ * Assume this as the limit of resources that
+ * can be provided to the split and unpack
+ * requests.
+ */
+
+#define NXNumberOfResources 256
+
+#define NXNoResource 256 + 1
+#define NXAnyResource 256 + 2
+
+/*
+ * Initialize the internal structures used by
+ * the library. Should be executed again after
+ * having reopened the display.
+ */
+
+extern int NXInitDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Reset all the internal structures. Should be
+ * executed after closing the display.
+ */
+
+extern int NXResetDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Set the NX display flush policy. The policy can
+ * be either NXFlushDeferred or NXFlushImmediate.
+ */
+
+extern int NXSetDisplayPolicy(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* policy */
+#endif
+);
+
+/*
+ * Set the display output buffer size.
+ */
+
+extern int NXSetDisplayBuffer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* size */
+#endif
+);
+
+/*
+ * If set, the Popen() function in the X server
+ * wil remove the LD_LIBRARY_PATH variable from
+ * the environment before calling the execl()
+ * function on the child process. The function
+ * returns the previous value.
+ */
+
+extern int NXUnsetLibraryPath(
+#if NeedFunctionPrototypes
+ int /* value */
+#endif
+);
+
+/*
+ * If the parameter is true, the Xlib I/O error
+ * handler will return, instead of quitting the
+ * program. The function returns the previous
+ * value.
+ */
+
+extern int NXHandleDisplayError(
+#if NeedFunctionPrototypes
+ int /* value */
+#endif
+);
+
+/*
+ * Shutdown the display descriptor and force Xlib
+ * to set the I/O error flag.
+ */
+
+extern Bool NXForceDisplayError(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Check the value of the XlibDisplayIOError flag.
+ * If not set, try to call the display error hand-
+ * ler to give to the application a chance to see
+ * whether it needs to close the connection.
+ */
+
+extern int NXDisplayError(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Query the number of bytes readable from the
+ * display connection.
+ */
+
+extern int NXDisplayReadable(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Query the number of the outstanding bytes to
+ * flush to the display connection.
+ */
+
+extern int NXDisplayFlushable(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Return a value between 0 and 9 indicating the
+ * congestion level of the NX transport based on
+ * the tokens remaining. A value of 9 means that
+ * the link is congested and no further data can
+ * be sent.
+ */
+
+extern int NXDisplayCongestion(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+/*
+ * Flush the Xlib display buffer and/or the
+ * outstanding data accumulated by the NX
+ * transport.
+ */
+
+extern int NXFlushDisplay(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* what */
+#endif
+);
+
+/*
+ * Public interfaces used to set the handlers.
+ * They all return the previous handler.
+ */
+
+extern NXDisplayErrorPredicate NXSetDisplayErrorPredicate(
+#if NeedFunctionPrototypes
+ NXDisplayErrorPredicate /* predicate */
+#endif
+);
+
+/*
+ * Called when the display blocks waiting to read or
+ * write more data.
+ */
+
+extern NXDisplayBlockHandler NXSetDisplayBlockHandler(
+#if NeedFunctionPrototypes
+ NXDisplayBlockHandler /* handler */
+#endif
+);
+
+/*
+ * Called after more data is written to the display.
+ * When the NX transport is running, data may be queued
+ * until an explicit flush.
+ */
+
+extern NXDisplayWriteHandler NXSetDisplayWriteHandler(
+#if NeedFunctionPrototypes
+ NXDisplayWriteHandler /* handler */
+#endif
+);
+
+/*
+ * Called after more data is sent to the remote proxy.
+ *
+ * Here the display pointer is passed as the second
+ * parameter to make clear that the function does not
+ * tie the callback to the display, but, similarly to
+ * all the Xlib error handlers, to a global variable
+ * shared by all the Xlib functions. The display
+ * pointer will be passed back by nxcomp at the time
+ * it will call the handler. This is because nxcomp
+ * doesn't have access to the display structure.
+ */
+
+extern NXDisplayFlushHandler NXSetDisplayFlushHandler(
+#if NeedFunctionPrototypes
+ NXDisplayFlushHandler /* handler */,
+ Display* /* display */
+#endif
+);
+
+/*
+ * Get an arbitrary null terminated buffer to be added
+ * to the NX statistics.
+ */
+
+extern NXDisplayStatisticsHandler NXSetDisplayStatisticsHandler(
+#if NeedFunctionPrototypes
+ NXDisplayStatisticsHandler /* handler */,
+ char ** /* buffer */
+#endif
+);
+
+/*
+ * Redefine the function called by Xlib in the case of
+ * an out-of-order sequence number received in the X
+ * protocol stream.
+ */
+
+extern NXLostSequenceHandler NXSetLostSequenceHandler(
+#if NeedFunctionPrototypes
+ NXLostSequenceHandler /* handler */
+#endif
+);
+
+/*
+ * The agent should get the NX parameters at startup, just after
+ * having opened the display. If the agent is not able to satisfy
+ * the pack method set by user (because a method is not applica-
+ * ble, it is not supported by the remote or it simply requires a
+ * screen depth greater than the depth available), it should fall
+ * back to the nearest method of the same type.
+ */
+
+extern Status NXGetControlParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* link_type */,
+ unsigned int* /* local_major */,
+ unsigned int* /* local_minor */,
+ unsigned int* /* local_patch */,
+ unsigned int* /* remote_major */,
+ unsigned int* /* remote_minor */,
+ unsigned int* /* remote_patch */,
+ int* /* frame_timeout */,
+ int* /* ping_timeout */,
+ int* /* split_mode */,
+ int* /* split_size */,
+ unsigned int* /* pack_method */,
+ unsigned int* /* pack_quality */,
+ int* /* data_level */,
+ int* /* stream_level */,
+ int* /* delta_level */,
+ unsigned int* /* load_cache */,
+ unsigned int* /* save_cache */,
+ unsigned int* /* startup_cache */
+#endif
+);
+
+/*
+ * Which unpack methods are supported by the remote proxy?
+ */
+
+extern Status NXGetUnpackParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* entries */,
+ unsigned char[] /* supported_methods */
+#endif
+);
+
+/*
+ * Query and enable shared memory support on path agent to X
+ * client proxy and X server proxy to real X server. At the
+ * moment only the path proxy to real X server is implemented.
+ * On return flags will say if support has been successfully
+ * activated. Segments will contain the XID associated to the
+ * shared memory blocks. A MIT-SHM compliant protocol is used
+ * between proxy and the real server, while a simplified
+ * version is used between the agent and the client proxy to
+ * accomodate both packed images and plain X bitmaps.
+ */
+
+extern Status NXGetShmemParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int* /* enable_client */,
+ unsigned int* /* enable_server */,
+ unsigned int* /* client_segment */,
+ unsigned int* /* server_segment */,
+ unsigned int* /* client_size */,
+ unsigned int* /* server_size */
+#endif
+);
+
+/*
+ * Get the path to the font server that can be used by the X
+ * server to tunnel the font connections across the NX link.
+ * The path actually represents the TCP port where the proxy
+ * on the NX client side is listening. The agent can tempora-
+ * rily enable the tunneling when it needs a font that is not
+ * available on the client, for example when the session is
+ * migrated from a different X server.
+ */
+
+extern Status NXGetFontParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* path_length */,
+ char[] /* path_data */
+#endif
+);
+
+/*
+ * This set of functions is used to leverage the image stream-
+ * ing capabilities built in nxcomp. An image can be streamed
+ * by sending a start-split message, followed by the X messages
+ * that will have to be split by the proxy, followed by an end-
+ * split closure. Usually, in the middle of a start-split/end-
+ * split sequence there will be a single PutImage() or PutPack-
+ * edImage(), that, in turn, can generate multiple partial
+ * requests, like a SetUnpackColormap() and SetUnpackAlpha()
+ * that will be later used to decompress the image to its ori-
+ * ginal form. Multiple requests may be also generated because
+ * of the maximum size of a X request being exceeded, so that
+ * Xlib has to divide the single image in multiple sub-image re-
+ * quests. The agent doesn't need to take care of these details
+ * but will rather have to track the result of the split opera-
+ * tion. By monitoring the notify events sent by the proxy, the
+ * agent will have to implement its own strategy to deal with
+ * the resources. For example, it will be able to:
+ *
+ * - Mark a drawable as dirty, if the image was not sent
+ * synchronously, in the main X oputput stream.
+ *
+ * - Choose to commit or discard the original image, at the
+ * time it will be recomposed at the remote side. This may
+ * include all the messages that were part of the split
+ * (the colormap, the alpha channel, etc.)
+ *
+ * - Mark the drawable as clean again, if the image was
+ * committed and the drawable didn't change in the mean-
+ * while.
+ *
+ * At the time the proxy receives the end-split, it reports the
+ * result of the operation to the agent. The agent will be able
+ * to identify the original split operation (the one referenced
+ * in the start-split/end-split sequence) by the small integer
+ * number (0-255) named 'resource' sent in the events.
+ *
+ * One of the following cases may be encountered:
+ *
+ *
+ * NXNoSplitNotify All messages were sent in the main out-
+ * put stream, so that no split actually
+ * took place.
+ *
+ * NXStartSplitNotify One or more messages were split, so,
+ * at discrection of the agent, the client
+ * may be suspended until the transferral
+ * is completed.
+ *
+ * NXCommitSplitNotify One of the requests that made up the
+ * split was recomposed. The agent should
+ * either commit the given request or tell
+ * the proxy to discard it.
+ *
+ * NXEndSplitNotify The split was duly completed. The agent
+ * can restart the client.
+ *
+ * NXEmptySplitNotify No more split operation are pending.
+ * The agent can use this information to
+ * implement specific strategies requiring
+ * that all messages have been recomposed
+ * at the remote end, like updating the
+ * drawables that were not synchronized
+ * because of the lazy encoding.
+ *
+ * The 'mode' field that is sent by the agent in the start-split
+ * request, determines the strategy that the proxy will adopt to
+ * deal with the image. If set to 'eager', the proxy will only
+ * split the messages whose size exceeds the split threshold (the
+ * current threshold can be found in the NXGetControlParameters()
+ * reply). If the mode is set to lazy, the proxy will split any
+ * image that would have generated an actual transfer of the data
+ * part (in practice all images that are not found in the cache).
+ * This second strategy can be leveraged by an agent to further
+ * reduce the bandwidth requirements. For example, by setting the
+ * mode to lazy and by monitoring the result, an agent can easi-
+ * ly verify if the drawable was successfully updated, mark the
+ * drawable if not, and synchronize it at later time.
+ *
+ * See NXproto.h for the definition of the available modes.
+ */
+
+extern unsigned int NXAllocSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXStartSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* mode */
+#endif
+);
+
+extern int NXEndSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXCommitSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* propagate */,
+ unsigned char /* request */,
+ unsigned int /* position */
+#endif
+);
+
+extern int NXAbortSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXFinishSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXFreeSplit(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXSetExposeParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* expose */,
+ int /* graphics_expose */,
+ int /* no_expose */
+#endif
+);
+
+extern int NXSetCacheParameters(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* enable_cache */,
+ int /* enable_split */,
+ int /* enable_save */,
+ int /* enable_load */
+#endif
+);
+
+extern unsigned int NXAllocUnpack(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXSetUnpackGeometry(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Visual* /* visual */
+#endif
+);
+
+extern int NXSetUnpackColormap(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* method */,
+ unsigned int /* entries */,
+ const char* /* data */,
+ unsigned int /* data_length */
+#endif
+);
+
+extern int NXSetUnpackAlpha(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* method */,
+ unsigned int /* entries */,
+ const char* /* data */,
+ unsigned int /* data_length */
+#endif
+);
+
+extern int NXSetUnpackColormapCompat(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* entries */,
+ const char* /* data */
+#endif
+);
+
+extern int NXSetUnpackAlphaCompat(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ unsigned int /* entries */,
+ const char* /* data */
+#endif
+);
+
+extern int NXFreeUnpack(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+/*
+ * A packed image is a XImage but with
+ * offset field containing total amount
+ * of packed image data.
+ */
+
+typedef XImage NXPackedImage;
+
+NXPackedImage *NXCreatePackedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ Visual* /* visual */,
+ unsigned int /* method */,
+ unsigned int /* depth */,
+ int /* format */,
+ char* /* data */,
+ int /* data_length */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ int /* bitmap_pad */,
+ int /* bytes_per_line */
+#endif
+);
+
+extern int NXDestroyPackedImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* image */
+#endif
+);
+
+NXPackedImage *NXPackImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ XImage* /* src_image */,
+ unsigned int /* method */
+#endif
+);
+
+NXPackedImage *NXInPlacePackImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ XImage* /* src_image */,
+ unsigned int /* method */
+#endif
+);
+
+/*
+ * GC is declared void * to get rid of mess
+ * with different GC definitions in some X
+ * server code (like in nxagent).
+ */
+
+extern int NXPutPackedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Drawable /* drawable */,
+ void* /* gc */,
+ NXPackedImage* /* image */,
+ unsigned int /* method */,
+ unsigned int /* depth */,
+ int /* src_x */,
+ int /* src_y */,
+ int /* dst_x */,
+ int /* dst_y */,
+ unsigned int /* width */,
+ unsigned int /* height */
+#endif
+);
+
+/*
+ * Get multiple colors with a single call by
+ * pipelining X_AllocColor requests/replies.
+ */
+
+extern int NXAllocColors(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ Colormap /* colormap */,
+ unsigned int /* entries */,
+ XColor[] /* screens_in_out */,
+ Bool [] /* flags allocation errors */
+#endif
+);
+
+/*
+ * Encode the data in the given format.
+ */
+
+extern char *NXEncodeColormap(
+#if NeedFunctionPrototypes
+ const char* /* src_data */,
+ unsigned int /* src_size */,
+ unsigned int* /* dst_size */
+#endif
+);
+
+extern char *NXEncodeAlpha(
+#if NeedFunctionPrototypes
+ const char* /* src_data */,
+ unsigned int /* src_size */,
+ unsigned int* /* dst_size */
+#endif
+);
+
+extern NXPackedImage *NXEncodeRgb(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeRle(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeJpeg(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+typedef struct
+{
+ long pixel;
+ int found;
+
+} NXColorTable;
+
+extern int NXEncodeColors(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ int /* nb_max */
+#endif
+);
+
+extern NXPackedImage *NXEncodePng(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern NXPackedImage *NXEncodeBitmap(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ unsigned int /* method */,
+ unsigned int /* quality */
+#endif
+);
+
+extern int NXCleanImage(
+#if NeedFunctionPrototypes
+ XImage*
+#endif
+);
+
+extern void NXMaskImage(
+#if NeedFunctionPrototypes
+ XImage* /* pointer to image to mask */ ,
+ unsigned int /* method */
+#endif
+);
+
+extern int NXImageCacheSize;
+
+extern void NXInitCache(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ int /* entries in image cache */
+#endif
+);
+
+extern void NXFreeCache(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern XImage *NXCacheFindImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* packed image to find */,
+ unsigned int* /* pointer to the pack method if found */,
+ unsigned char** /* pointer to the calculated MD5 if found */
+#endif
+);
+
+extern int NXCacheAddImage(
+#if NeedFunctionPrototypes
+ NXPackedImage* /* packed image to be added to the cache */,
+ unsigned int /* pack method of the image to add */,
+ unsigned char* /* pointer to MD5 of the original unpacked image */
+#endif
+);
+
+
+extern int NXGetCollectImageResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Drawable /* drawable */,
+ int /* src_x */,
+ int /* src_y */,
+ unsigned int /* width */,
+ unsigned int /* height */,
+ unsigned long /* plane_mask */,
+ int /* format */
+#endif
+);
+
+extern int NXGetCollectedImage(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ XImage** /* image */
+#endif
+);
+
+extern int NXGetCollectPropertyResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectProperty(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window /* window */,
+ Atom /* property */,
+ long /* long_offset */,
+ long /* long_length */,
+ Bool /* delete */,
+ Atom /* req_type */
+#endif
+);
+
+extern int NXGetCollectedProperty(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Atom* /* actual_type_return */,
+ int* /* actual_format_return */,
+ unsigned long* /* nitems_return */,
+ unsigned long* /* bytes_after_return */,
+ unsigned char** /* data */
+#endif
+);
+
+extern int NXGetCollectGrabPointerResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectGrabPointer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window /* grab_window */,
+ Bool /* owner_events */,
+ unsigned int /* event_mask */,
+ int /* pointer_mode */,
+ int /* keyboard_mode */,
+ Window /* confine_to */,
+ Cursor /* cursor */,
+ Time /* time */
+#endif
+);
+
+extern int NXGetCollectedGrabPointer(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ int* /* status */
+#endif
+);
+
+extern int NXGetCollectInputFocusResource(
+#if NeedFunctionPrototypes
+ Display* /* display */
+#endif
+);
+
+extern int NXCollectInputFocus(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */
+#endif
+);
+
+extern int NXGetCollectedInputFocus(
+#if NeedFunctionPrototypes
+ Display* /* display */,
+ unsigned int /* resource */,
+ Window* /* focus_return */,
+ int* /* revert_to_return */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NXlib_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile b/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile
new file mode 100644
index 000000000..8f0f17d1e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Imakefile
@@ -0,0 +1,48 @@
+NULL =
+
+#include <Server.tmpl>
+
+SRCS = \
+ Alpha.c \
+ Bitmap.c \
+ Clean.c \
+ Colormap.c \
+ Compext.c \
+ Jpeg.c \
+ Mask.c \
+ Png.c \
+ Rgb.c \
+ Rle.c \
+ Z.c \
+ $(NULL)
+
+OBJS = \
+ Alpha.o \
+ Bitmap.o \
+ Clean.o \
+ Colormap.o \
+ Compext.o \
+ Jpeg.o \
+ Mask.o \
+ Png.o \
+ Rgb.o \
+ Rle.o \
+ Z.o \
+ $(NULL)
+
+ INCLUDES = -I$(SERVERSRC)/include \
+ -I$(XBUILDINCDIR) \
+ `pkg-config --cflags-only-I pixman-1` \
+ `pkg-config --cflags-only-I zlib` \
+ `pkg-config --cflags-only-I libpng` \
+ $(NULL)
+
+ LINTLIBS = $(SERVERSRC)/dix/llib-ldix.ln \
+ $(NULL)
+
+NormalLibraryObjectRule()
+NormalLibraryTarget(compext,$(OBJS))
+LintLibraryTarget(compext,$(SRCS))
+NormalLintTarget($(SRCS))
+
+DependTarget()
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c
new file mode 100644
index 000000000..690a934f6
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.c
@@ -0,0 +1,480 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xmd.h>
+
+#include <jpeglib.h>
+
+#include "Compext.h"
+
+#include "Mask.h"
+#include "Jpeg.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define JPEG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024)
+
+/*
+ * Local function prototypes.
+ */
+
+static void PrepareRowForJpeg(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg24(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg16(CARD8 *dst, int y, int count);
+static void PrepareRowForJpeg32(CARD8 *dst, int y, int count);
+
+static int JpegEmptyOutputBuffer(j_compress_ptr cinfo);
+
+static void JpegInitDestination(j_compress_ptr cinfo);
+static void JpegTermDestination(j_compress_ptr cinfo);
+static void JpegSetDstManager(j_compress_ptr cinfo);
+
+/*
+ * Quality levels.
+ */
+
+static int jpegQuality[10] = {20, 30, 40, 50, 55, 60, 65, 70, 75, 80};
+
+/*
+ * Image characteristics.
+ */
+
+static int bytesPerLine;
+
+static CARD8 bitsPerPixel;
+static CARD16 redMax, greenMax, blueMax;
+static CARD8 redShift, greenShift, blueShift;
+static int byteOrder;
+
+/*
+ * Other variables used for the Jpeg
+ * encoding.
+ */
+
+static char *jpegBeforeBuf = NULL;
+static char *jpegCompBuf;
+static int jpegCompBufSize;
+static int jpegError;
+static int jpegDstDataLen;
+
+static struct jpeg_destination_mgr jpegDstManager;
+
+/*
+ * Just for debugging purpose.
+ */
+
+#ifdef DEBUG
+
+static int jpegId;
+static char jpegName[10];
+static FILE *jpegFile;
+
+#endif
+
+/*
+ * Function declarations
+ */
+
+char *JpegCompressData(XImage *image, int level, int *compressed_size)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ CARD8 *srcBuf;
+ JSAMPROW rowPointer[1];
+
+ int dy, w, h;
+
+ *compressed_size = 0;
+
+ /*
+ * Initialize the image stuff
+ */
+
+ bitsPerPixel = image -> bits_per_pixel;
+ bytesPerLine = image -> bytes_per_line;
+ byteOrder = image -> byte_order;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Image byte order [%d] bitmap bit order [%d].\n",
+ image -> byte_order, image -> bitmap_bit_order);
+
+ fprintf(stderr, "******JpegCompressData: Bits per pixel [%d] bytes per line [%d].\n",
+ bitsPerPixel, bytesPerLine);
+ #endif
+
+ redShift = FindLSB(image -> red_mask) - 1;
+ greenShift = FindLSB(image -> green_mask) - 1;
+ blueShift = FindLSB(image -> blue_mask) - 1;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Red mask [0x%lx] green mask [0x%lx] blue mask [0x%lx].\n",
+ image -> red_mask, image -> green_mask, image -> blue_mask);
+
+ fprintf(stderr, "******JpegCompressData: Red shift [%d] green shift [%d] blue shift [%d].\n",
+ redShift, greenShift, blueShift);
+ #endif
+
+ redMax = image -> red_mask >> redShift;
+ greenMax = image -> green_mask >> greenShift;
+ blueMax = image -> blue_mask >> blueShift;
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Red max [0x%x] green max [0x%x] blue max [0x%x].\n",
+ redMax, greenMax, blueMax);
+ #endif
+
+ w = image -> width;
+ h = image -> height;
+
+ jpegBeforeBuf = image -> data;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressData: Width [%d] height [%d] level [%d].\n",
+ w, h, level);
+ #endif
+
+ if (bitsPerPixel == 1 ||
+ bitsPerPixel == 8)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Invalid bits per pixel [%d].\n",
+ bitsPerPixel);
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * Allocate space for one line of the
+ * resulting image, 3 bytes per pixel.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the scanline.\n",
+ w * 3);
+ #endif
+
+ srcBuf = (CARD8 *) malloc(w * 3);
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ w * 3);
+ #endif
+
+ return NULL;
+ }
+
+ rowPointer[0] = srcBuf;
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jpeg_create_compress(&cinfo);
+
+ cinfo.image_width = w;
+ cinfo.image_height = h;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, jpegQuality[level], 1);
+
+ /*
+ * Allocate memory for the destination
+ * buffer.
+ */
+
+ jpegCompBufSize = JPEG_DEST_SIZE(w, h);
+
+ #ifdef TEST
+ fprintf(stderr, "******JpegCompressData: Allocating [%d] bytes for the destination data.\n",
+ jpegCompBufSize);
+ #endif
+
+ jpegCompBuf = malloc(jpegCompBufSize);
+
+ if (jpegCompBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressData: PANIC! Error allocating [%d] bytes for the Jpeg data.\n",
+ jpegCompBufSize);
+ #endif
+
+ return NULL;
+ }
+
+ JpegSetDstManager(&cinfo);
+
+ jpeg_start_compress(&cinfo, 1);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressedData: Initialization finished.\n");
+ #endif
+
+ for (dy = 0; dy < h; dy++)
+ {
+ PrepareRowForJpeg(srcBuf, dy, w);
+
+ jpeg_write_scanlines(&cinfo, rowPointer, 1);
+
+ if (jpegError != 0)
+ {
+ break;
+ }
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******JpegCompressedData: Compression finished. Lines handled [%d,%d]. Error is [%d].\n",
+ dy, h, jpegError);
+ #endif
+
+ if (jpegError == 0)
+ {
+ jpeg_finish_compress(&cinfo);
+ }
+
+ jpeg_destroy_compress(&cinfo);
+
+ free((char *) srcBuf);
+
+ if (jpegError != 0)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressedData: PANIC! Compression failed. Error is [%d].\n",
+ jpegError);
+ #endif
+
+ free(jpegCompBuf);
+
+ return NULL;
+ }
+
+ /*
+ * Check the size of the resulting data.
+ */
+
+ if (jpegDstDataLen > 0)
+ {
+ /*
+ * Save the image on disk to help with
+ * the debug.
+ */
+
+ #ifdef DEBUG
+
+ int i = 0;
+
+ fprintf(stderr, "******JpegCompressedData: Compressed size [%d].\n",
+ jpegDstDataLen);
+
+ jpegId++;
+
+ sprintf(jpegName, "jpeg%d", jpegId);
+
+ jpegFile = fopen(jpegName, "w");
+
+ for (i = 0; i < jpegDstDataLen; i++)
+ {
+ fprintf(jpegFile, "%c", *(jpegCompBuf + i));
+ }
+
+ fclose(jpegFile);
+
+ #endif
+
+ *compressed_size = jpegDstDataLen;
+
+ return jpegCompBuf;
+ }
+ else
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******JpegCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
+ jpegDstDataLen);
+ #endif
+
+ free(jpegCompBuf);
+
+ return NULL;
+ }
+}
+
+void PrepareRowForJpeg(CARD8 *dst, int y, int count)
+{
+ if (bitsPerPixel == 32)
+ {
+ if (redMax == 0xff &&
+ greenMax == 0xff &&
+ blueMax == 0xff)
+ {
+ PrepareRowForJpeg24(dst, y, count);
+ }
+ else
+ {
+ PrepareRowForJpeg32(dst, y, count);
+ }
+ }
+ else if (bitsPerPixel == 24)
+ {
+ memcpy(dst, jpegBeforeBuf + y * bytesPerLine, count * 3);
+ }
+ else
+ {
+ /*
+ * 16 bpp assumed.
+ */
+
+ PrepareRowForJpeg16(dst, y, count);
+ }
+}
+
+void PrepareRowForJpeg24(CARD8 *dst, int y, int count)
+{
+ CARD8 *fbptr;
+ CARD32 pix;
+
+ fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine);
+
+ while (count--)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pix = (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr+1);
+ pix = (pix << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pix = (CARD32) *(fbptr + 1);
+ pix = (pix << 8) | (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ *dst++ = (CARD8)(pix >> redShift);
+ *dst++ = (CARD8)(pix >> greenShift);
+ *dst++ = (CARD8)(pix >> blueShift);
+
+ fbptr+=4;
+ }
+}
+
+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
+ \
+void PrepareRowForJpeg##bpp(CARD8 *dst, int y, int count) \
+{ \
+ CARD8 *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ int i; \
+ \
+ fbptr = (CARD8 *) (jpegBeforeBuf + y * bytesPerLine); \
+ \
+ while (count--) \
+ { \
+ pix = 0; \
+ \
+ if (byteOrder == LSBFirst) \
+ { \
+ for (i = (bpp >> 3) - 1; i >= 0; i--) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ else \
+ { \
+ for (i = 0; i < (bpp >> 3); i++) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ \
+ fbptr += bpp >> 3; \
+ \
+ inRed = (int) \
+ (pix >> redShift & redMax); \
+ inGreen = (int) \
+ (pix >> greenShift & greenMax); \
+ inBlue = (int) \
+ (pix >> blueShift & blueMax); \
+ \
+ *dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
+ redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
+ greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
+ blueMax); \
+ } \
+}
+
+DEFINE_JPEG_GET_ROW_FUNCTION(16)
+DEFINE_JPEG_GET_ROW_FUNCTION(32)
+
+/*
+ * Destination manager implementation for JPEG library.
+ */
+
+void JpegInitDestination(j_compress_ptr cinfo)
+{
+ jpegError = 0;
+
+ jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
+ jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
+}
+
+int JpegEmptyOutputBuffer(j_compress_ptr cinfo)
+{
+ jpegError = 1;
+
+ jpegDstManager.next_output_byte = (JOCTET *) jpegCompBuf;
+ jpegDstManager.free_in_buffer = (size_t) jpegCompBufSize;
+
+ return 1;
+}
+
+void JpegTermDestination(j_compress_ptr cinfo)
+{
+ jpegDstDataLen = jpegCompBufSize - jpegDstManager.free_in_buffer;
+}
+
+void JpegSetDstManager(j_compress_ptr cinfo)
+{
+ jpegDstManager.init_destination = JpegInitDestination;
+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer;
+ jpegDstManager.term_destination = JpegTermDestination;
+
+ cinfo -> dest = &jpegDstManager;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h
new file mode 100644
index 000000000..b50efd3ec
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Jpeg.h
@@ -0,0 +1,46 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Jpeg_H
+#define Jpeg_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *JpegCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ int /* level */,
+ int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Jpeg_H */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c
new file mode 100644
index 000000000..cdcb8d3c0
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.c
@@ -0,0 +1,802 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+
+#include <nx-X11/Xlib.h>
+
+#include <nx/NXpack.h>
+
+#include "Mask.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Try first to reduce to a white or black
+ * pixel. If not possible, apply the mask.
+ * Note that correction is applied at the
+ * time pixel is unpacked.
+ */
+
+#define MaskPixel(red, green, blue, mask) \
+\
+if (red > mask -> white_threshold && \
+ green > mask -> white_threshold && \
+ blue > mask -> white_threshold) \
+{ \
+ red = green = blue = 0xff; \
+} \
+else if (red < mask -> black_threshold && \
+ green < mask -> black_threshold && \
+ blue < mask -> black_threshold) \
+{ \
+ red = green = blue = 0x00; \
+} \
+else \
+{ \
+ red = red & mask -> color_mask; \
+ green = green & mask -> color_mask; \
+ blue = blue & mask -> color_mask; \
+}
+
+int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image)
+{
+ unsigned long pixel;
+
+ register unsigned int red;
+ register unsigned int green;
+ register unsigned int blue;
+
+ register unsigned long data_size;
+
+ register unsigned int i;
+
+ data_size = (src_image -> bytes_per_line * src_image -> height) >> 2;
+
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: Going to mask image with [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ if (src_image -> bits_per_pixel == 24 || src_image -> bits_per_pixel == 32)
+ {
+ register unsigned char *pixel_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ pixel = ((unsigned long *) src_image -> data)[i];
+
+ pixel_addr = (unsigned char *) &pixel;
+
+ red = pixel_addr[2];
+ green = pixel_addr[1];
+ blue = pixel_addr[0];
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 24/32 bits pixel 0x%lx", pixel);
+ #endif
+
+ pixel_addr[2] = red;
+ pixel_addr[1] = green;
+ pixel_addr[0] = blue;
+
+ ((unsigned long*)dst_image -> data)[i] = pixel;
+
+ #ifdef DEBUG
+ fprintf(stderr, " -> 0x%lx\n", pixel);
+ #endif
+ }
+
+ return 1;
+ }
+ else if (src_image -> bits_per_pixel == 16)
+ {
+ /*
+ * FIXME: Masking doesn't work in 16 bpp.
+ *
+
+ unsigned long src_addr, *dst_addr;
+ unsigned short *src_pixels_addr, *dst_pixels_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ src_addr = ((unsigned long *)src_image -> data)[i];
+ dst_addr = (unsigned long *)((unsigned long *)dst_image -> data + i);
+
+ src_pixels_addr = ((unsigned short *) &src_addr);
+ dst_pixels_addr = ((unsigned short *) dst_addr);
+
+ red = (src_pixels_addr[0] & src_image -> red_mask) >> 8;
+ green = (src_pixels_addr[0] & src_image -> green_mask) >> 3;
+ blue = (src_pixels_addr[0] & src_image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ dst_pixels_addr[0] = ((red << 8) & src_image -> red_mask) |
+ ((green << 3) & src_image -> green_mask) |
+ ((blue >> 3) & src_image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
+ #endif
+
+ red = (src_pixels_addr[1] & src_image -> red_mask) >> 8;
+ green = (src_pixels_addr[1] & src_image -> green_mask) >> 3;
+ blue = (src_pixels_addr[1] & src_image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ dst_pixels_addr[1] = ((red << 8) & src_image -> red_mask) |
+ ((green << 3) & src_image -> green_mask) |
+ ((blue >> 3) & src_image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskImage: 16 bits pixel 0x%x", dst_pixels_addr[0]);
+ #endif
+ }
+
+ if (dst_image -> width & 0x00000001)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = dst_image -> bytes_per_line >> 2;
+
+ for (i = 0; i < dst_image -> height;)
+ {
+ ((CARD32 *) dst_image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
+ }
+ }
+
+ *
+ * End of FIXME.
+ */
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
+ src_image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ return 1;
+}
+
+int MaskInPlaceImage(const ColorMask *mask, XImage *image)
+{
+ unsigned long pixel;
+
+ register unsigned int red;
+ register unsigned int green;
+ register unsigned int blue;
+
+ register unsigned int i;
+
+ register unsigned long data_size;
+
+ data_size = (image -> bytes_per_line * image -> height)>>2;
+
+ #ifdef TEST
+ fprintf(stderr, "******MaskInPlaceImage: Going to mask image with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ if (image -> bits_per_pixel == 24 || image -> bits_per_pixel == 32)
+ {
+ register unsigned char *pixel_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ pixel = ((unsigned long *) image -> data)[i];
+
+ pixel_addr = (unsigned char *) &pixel;
+
+ red = pixel_addr[2];
+ green = pixel_addr[1];
+ blue = pixel_addr[0];
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits original R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits masked R [%d] G [%d] B [%d] A [%d].\n",
+ red, green, blue, pixel_addr[3]);
+ #endif
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 24/32 bits pixel 0x%lx", pixel);
+ #endif
+
+ pixel_addr[2] = red;
+ pixel_addr[1] = green;
+ pixel_addr[0] = blue;
+
+ ((unsigned long *) image -> data)[i] = pixel;
+
+ #ifdef DEBUG
+ fprintf(stderr, " -> 0x%lx\n", pixel);
+ #endif
+ }
+
+ return 1;
+ }
+ else if (image -> bits_per_pixel == 16)
+ {
+ /*
+ * FIXME: Mask doesn't still work for 16 bits.
+ *
+
+ unsigned long addr;
+ register unsigned short *pixels_addr;
+
+ for (i = 0; i < data_size; i++)
+ {
+ addr = ((unsigned long *) image -> data)[i];
+
+ pixels_addr = ((unsigned short *) &addr);
+
+ red = (pixels_addr[0] & image -> red_mask) >> 8;
+ green = (pixels_addr[0] & image -> green_mask) >> 3;
+ blue = (pixels_addr[0] & image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ pixels_addr[0] = ((red << 8) & image -> red_mask) |
+ ((green << 3) & image -> green_mask) |
+ ((blue >> 3) & image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[0]);
+ #endif
+
+ red = (pixels_addr[1] & image -> red_mask) >> 8;
+ green = (pixels_addr[1] & image -> green_mask) >> 3;
+ blue = (pixels_addr[1] & image -> blue_mask) << 3;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits original R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ MaskPixel(red, green, blue, mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits masked R [%d] G [%d] B [%d].\n",
+ red, green, blue);
+ #endif
+
+ pixels_addr[1] = ((red << 8) & image -> red_mask) |
+ ((green << 3) & image -> green_mask) |
+ ((blue >> 3) & image -> blue_mask);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******MaskInPlaceImage: 16 bits pixel 0x%x", pixels_addr[1]);
+ #endif
+ }
+
+ if (image -> width & 0x00000001)
+ {
+ int card32_per_line;
+ int i;
+
+ card32_per_line = image -> bytes_per_line >> 2;
+
+ for (i = 0; i < image -> height;)
+ {
+ ((CARD32 *) image -> data)[(++i * card32_per_line) - 1] &= 0x0000ffff;
+ }
+ }
+
+ *
+ * End of FIXME.
+ */
+ }
+ else
+ {
+ #ifdef TEST
+ fprintf(stderr, "******MaskImage: PANIC! Cannot apply mask with [%d] bits per pixel.\n",
+ image -> bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ return 1;
+}
+
+static int Pack16To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned short *src_pixel = (unsigned short *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned short *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xc000) >> 8,
+ ((*src_pixel & 0x600) >> 3), (*src_pixel & 0x18) << 3);
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xc000) >> 10) |
+ ((*src_pixel & 0x600) >> 7) |
+ ((*src_pixel & 0x18) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack24To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned char *src_pixel = (unsigned char *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ int i;
+
+ unsigned int bytes_per_line = src_image -> bytes_per_line;
+
+ unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
+
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ for (i = 0; i < src_image -> height; i++ )
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xc0,
+ src_pixel[1] & 0xc0, src_pixel[2] & 0xc0);
+ #endif
+
+ while(src_pixel < end_of_line - 2)
+ {
+ if (src_pixel[0] == 0x00 &&
+ src_pixel[1] == 0x00 &&
+ src_pixel[2] == 0x00)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (src_pixel[0] == 0xff &&
+ src_pixel[1] == 0xff &&
+ src_pixel[2] == 0xff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ /*
+ * Pixel layout:
+ *
+ * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 8 bit 00RRGGBB
+ */
+
+ *dst_pixel = (src_pixel[0] & 0xc0) >> 2 |
+ ((src_pixel[1] & 0xc0) >> 4) |
+ ((src_pixel[2] & 0xc0) >> 6);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel += 3;
+ dst_pixel += 1;
+ }
+
+ src_pixel = end_of_line;
+ end_of_line += bytes_per_line;
+ }
+
+ return 1;
+}
+
+static int Pack24To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned char *src_pixel = (unsigned char *) src_image -> data;
+ unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
+
+ int i;
+
+ unsigned int bytes_per_line = src_image -> bytes_per_line;
+
+ unsigned char *end_of_line = (unsigned char *) (src_pixel + bytes_per_line);
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ for (i = 0; i < src_image -> height; i++ )
+ {
+ while(src_pixel < end_of_line - 2)
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x%x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, src_pixel[0], src_pixel[1], src_pixel[2], src_pixel[0] & 0xf8,
+ src_pixel[1] & 0xf8, src_pixel[2] & 0xf8);
+ #endif
+
+ if (src_pixel[0] == 0x00 &&
+ src_pixel[1] == 0x00 &&
+ src_pixel[2] == 0x00)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (src_pixel[0] == 0xff &&
+ src_pixel[1] == 0xff &&
+ src_pixel[2] == 0xff)
+ {
+ *dst_pixel = 0xffff;
+ }
+ else
+ {
+ /*
+ * Pixel layout:
+ *
+ * 24 bit RRRRR000 GGGGG000 BBBBB000 -> 16 bit 0RRRRRGG GGGBBBBB
+ */
+
+ *dst_pixel = ((src_pixel[0] & 0xf8) << 7) |
+ ((src_pixel[1] & 0xf8) << 2) |
+ ((src_pixel[2] & 0xf8) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel += 3;
+ dst_pixel += 1;
+ }
+
+ src_pixel = end_of_line;
+ end_of_line += bytes_per_line;
+ }
+
+ return 1;
+}
+
+static int Pack32To8(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xc00000),
+ (*src_pixel & 0xc000), (*src_pixel & 0xc0));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ *dst_pixel = 0xff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xc00000) >> 18) |
+ ((*src_pixel & 0xc000) >> 12) |
+ ((*src_pixel & 0xc0) >> 6);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack32To16(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned short *dst_pixel = (unsigned short *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, (*src_pixel & 0xf80000),
+ (*src_pixel & 0xf800), (*src_pixel & 0xf8));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ *dst_pixel = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ *dst_pixel = 0xffff;
+ }
+ else
+ {
+ *dst_pixel = ((*src_pixel & 0xf80000) >> 9) |
+ ((*src_pixel & 0xf800) >> 6) |
+ ((*src_pixel & 0xf8) >> 3);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x].\n",
+ counter++, *dst_pixel);
+ #endif
+
+ src_pixel++;
+ dst_pixel++;
+ }
+
+ return 1;
+}
+
+static int Pack32To24(unsigned int src_data_size, XImage *src_image, XImage *dst_image)
+{
+ unsigned int *src_pixel = (unsigned int *) src_image -> data;
+ unsigned char *dst_pixel = (unsigned char *) dst_image -> data;
+
+ #ifdef DEBUG
+ unsigned int counter = 0;
+ #endif
+
+ while (src_pixel < ((unsigned int *) (src_image -> data + src_data_size)))
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] value [0x%x] red [0x%x] green [0x%x] blue [0x%x].\n",
+ counter, *src_pixel, ((*src_pixel & 0xff0000) >> 16),
+ ((*src_pixel & 0x00ff00) >> 8), (*src_pixel & 0xff));
+ #endif
+
+ if (*src_pixel == 0x0)
+ {
+ dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0x0;
+ }
+ else if (*src_pixel == 0xffffff)
+ {
+ dst_pixel[0] = dst_pixel[1] = dst_pixel[2] = 0xff;
+ }
+ else
+ {
+ dst_pixel[0] = (*src_pixel & 0xff0000) >> 16;
+ dst_pixel[1] = (*src_pixel & 0x00ff00) >> 8;
+ dst_pixel[2] = (*src_pixel & 0x0000ff);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PackImage: Pixel [%d] destination [0x%x], [0x%x], [0x%x].\n",
+ counter++, dst_pixel[0], dst_pixel[1], dst_pixel[2]);
+ #endif
+
+ src_pixel += 1;
+ dst_pixel += 3;
+ }
+
+ return 1;
+}
+
+int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
+ unsigned int dst_data_size, XImage *dst_image)
+{
+ unsigned int src_bits_per_pixel;
+ unsigned int dst_bits_per_pixel;
+
+ src_bits_per_pixel = src_image -> bits_per_pixel;
+ dst_bits_per_pixel = MethodBitsPerPixel(method);
+
+ #ifdef TEST
+ fprintf(stderr, "******PackImage: Source bits per pixel [%d], destination bits per pixel [%d].\n",
+ src_bits_per_pixel, dst_bits_per_pixel);
+
+ fprintf(stderr, "******PackImage: Source data size [%d], destination data size [%d].\n",
+ src_data_size, dst_data_size);
+ #endif
+
+ if (dst_bits_per_pixel >= src_bits_per_pixel)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PackImage: PANIC! Cannot pack image from [%d] to [%d] bytes per pixel.\n",
+ src_bits_per_pixel, dst_bits_per_pixel);
+ #endif
+
+ return 0;
+ }
+
+ switch (src_bits_per_pixel)
+ {
+ case 16:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack16To8(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ case 24:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack24To8(src_data_size, src_image, dst_image);
+ }
+ case 16:
+ {
+ return Pack24To16(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ case 32:
+ {
+ switch (dst_bits_per_pixel)
+ {
+ case 8:
+ {
+ return Pack32To8(src_data_size, src_image, dst_image);
+ }
+ case 16:
+ {
+ return Pack32To16(src_data_size, src_image, dst_image);
+ }
+ case 24:
+ {
+ return Pack32To24(src_data_size, src_image, dst_image);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+/*
+ * Replace the ffs() call that may be not
+ * present on some systems.
+ */
+
+int FindLSB(int word)
+{
+ int t = word;
+
+ int m = 1;
+ int i = 0;
+
+ for (; i < sizeof(word) << 3; i++, m <<= 1)
+ {
+ if (t & m)
+ {
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h
new file mode 100644
index 000000000..1b6fe6d99
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Mask.h
@@ -0,0 +1,48 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Mask_H
+#define Mask_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Xlib.h"
+
+extern int MaskImage(const ColorMask *mask, XImage *src_image, XImage *dst_image);
+
+extern int MaskInPlaceImage(const ColorMask *mask, XImage *image);
+
+extern int PackImage(unsigned int method, unsigned int src_data_size, XImage *src_image,
+ unsigned int dst_data_size, XImage *dst_image);
+
+int FindLSB(int word);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Mask_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c
new file mode 100644
index 000000000..b235e095e
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.c
@@ -0,0 +1,730 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <nx-X11/Xutil.h>
+
+#include "Compext.h"
+
+#include "Mask.h"
+#include "Png.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+/*
+ * Selected ZLIB compression level.
+ */
+
+#define PNG_Z_LEVEL 4
+
+/*
+ * Local function prototypes.
+ */
+
+static void PrepareRowForPng(CARD8 *dst, int y, int count);
+static void PrepareRowForPng24(CARD8 *dst, int y, int count);
+static void PrepareRowForPng16(CARD8 *dst, int y, int count);
+static void PrepareRowForPng32(CARD8 *dst, int y, int count);
+
+static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length);
+static void PngFlushData(png_structp png_ptr);
+
+/*
+ * Image characteristics.
+ */
+
+static int bytesPerLine;
+static int byteOrder;
+
+static CARD8 bitsPerPixel;
+static CARD16 redMax, greenMax, blueMax;
+static CARD8 redShift, greenShift, blueShift;
+
+/*
+ * Other variables used for the Png
+ * encoding.
+ */
+
+png_byte color_type;
+png_structp png_ptr;
+png_infop info_ptr;
+png_colorp palette;
+static char *pngCompBuf;
+static int pngDataLen;
+static char *pngBeforeBuf = NULL;
+
+/*
+ * Allocate data for the compressed image.
+ * We need to ensure that there is enough
+ * space to include the palette and the
+ * header.
+ */
+
+#define PNG_DEST_SIZE(width, height) ((width) * 3 * (height) + 1024 + 256)
+
+/*
+ * Just for debug purposes.
+ */
+
+#ifdef DEBUG
+
+static int pngId;
+static char pngName[10];
+static FILE *pngFile;
+
+#endif
+
+int PngCompareColorTable(NXColorTable *c1, NXColorTable *c2)
+{
+ return (c1 -> pixel - c2 -> pixel);
+}
+
+#define NB_COLOR_MAX 256
+
+int NXCreatePalette32(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
+{
+ int x, y, t, p;
+ CARD8 *fbptr;
+ CARD32 pixel;
+
+ fbptr = (CARD8 *) (src_image -> data);
+
+ /*
+ * TODO: Find a more intelligent way to
+ * estimate the number of colors.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> height; x++)
+ {
+ for (y = 0; y < src_image -> width; y++)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pixel = (CARD32) *(fbptr + 3);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pixel = (CARD32) *fbptr;
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 2);
+ pixel = (pixel << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ fbptr += 4;
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if (color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+ p++;
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ else if ((CARD32)(color_table[t].pixel) == pixel)
+ {
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ }
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+ return p;
+}
+
+int NXCreatePalette16(XImage *src_image, NXColorTable *color_table, CARD8 *image_index, int nb_max)
+{
+ int x, y, t, p;
+ CARD8 *fbptr;
+ CARD16 pixel;
+
+ fbptr = (CARD8 *) (src_image -> data);
+
+ /*
+ * TODO: Find a more intelligent way to
+ * estimate the number of colors.
+ */
+
+ memset(color_table, 0, nb_max * sizeof(NXColorTable));
+
+ for (x = 0, p = 0; x < src_image -> height; x++)
+ {
+ for (y = 0; y < src_image -> width; y++)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pixel = (CARD16) *(fbptr + 1);
+ pixel = (pixel << 8) | (CARD16) *fbptr;
+ }
+ else
+ {
+ pixel = (CARD16) *fbptr;
+ pixel = (pixel << 8) | (CARD16) *(fbptr + 1);
+ }
+
+ fbptr += 2;
+
+ for (t = 0; t < nb_max; t++)
+ {
+ if (color_table[t].found == 0)
+ {
+ color_table[t].pixel = pixel;
+ color_table[t].found = 1;
+ p++;
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ else if ((color_table[t].pixel) == pixel)
+ {
+ image_index[((x * src_image -> width) + y)] = t;
+
+ break;
+ }
+ }
+
+ /*
+ * In case the number of 16bit words is not even
+ * we have 2 padding bytes that we have to skip.
+ */
+
+ if ((y == src_image -> width - 1) && (src_image -> width % 2 == 1)) fbptr += 2;
+
+ if (p == nb_max)
+ {
+ return nb_max + 1;
+ }
+ }
+ }
+
+ return p;
+}
+
+char *PngCompressData(XImage *image, int *compressed_size)
+{
+ unsigned int num = 0;
+ CARD8 *srcBuf;
+
+ int dy, w, h;
+
+ int nb_colors;
+
+ NXColorTable color_table[NB_COLOR_MAX];
+ CARD8 *image_index;
+
+ image_index = (CARD8 *) malloc((image -> height) * (image -> width) * sizeof(CARD8));
+
+ /*
+ * TODO: Be sure the padded bytes are cleaned.
+ * It would be better to set to zero the bytes
+ * that are not alligned to the word boundary
+ * at the end of the procedure.
+ */
+
+ memset(image_index, 0, (image -> height) * (image -> width) * sizeof(CARD8));
+
+ *compressed_size = 0;
+
+ pngDataLen = 0;
+
+ /*
+ * Initialize the image stuff.
+ */
+
+ bitsPerPixel = image -> bits_per_pixel;
+ bytesPerLine = image -> bytes_per_line;
+ byteOrder = image -> byte_order;
+
+ if (bitsPerPixel < 15)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Can't compress images with [%d] bits per pixel.\n",
+ bitsPerPixel);
+ #endif
+
+ return NULL;
+ }
+
+ redShift = FindLSB(image -> red_mask) - 1;
+ greenShift = FindLSB(image -> green_mask) - 1;
+ blueShift = FindLSB(image -> blue_mask) - 1;
+
+ redMax = image -> red_mask >> redShift;
+ greenMax = image -> green_mask >> greenShift;
+ blueMax = image -> blue_mask >> blueShift;
+
+ w = image -> width;
+ h = image -> height;
+ pngBeforeBuf = image -> data;
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressData: Compressing image with width [%d] height [%d].\n",
+ w, h );
+ #endif
+
+ /*
+ * Initialize the PNG stuff.
+ */
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (png_ptr == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_write_struct.\n");
+ #endif
+
+ return NULL;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Failed creating the png_create_info_struct.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, NULL);
+
+ return NULL;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error during compression initialization.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return NULL;
+ }
+
+ /*
+ * Be sure we allocate enough data.
+ */
+
+ #ifdef TEST
+ fprintf(stderr, "******PngCompressData: Allocating [%d] bytes for the destination data.\n",
+ PNG_DEST_SIZE(w, h));
+ #endif
+
+ pngCompBuf = malloc(PNG_DEST_SIZE(w, h));
+
+ if (pngCompBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error allocating [%d] bytes for the Png data.\n",
+ PNG_DEST_SIZE(w, h));
+ #endif
+
+ return NULL;
+ }
+
+ png_set_write_fn(png_ptr, (void *) pngCompBuf, PngWriteData, PngFlushData);
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error writing the header.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ png_set_compression_level(png_ptr, PNG_Z_LEVEL);
+
+ if (bitsPerPixel == 16)
+ {
+ nb_colors = NXCreatePalette16(image, color_table, image_index, NB_COLOR_MAX);
+ }
+ else
+ {
+ nb_colors = NXCreatePalette32(image, color_table, image_index, NB_COLOR_MAX);
+ }
+
+ if (nb_colors <= NB_COLOR_MAX)
+ {
+ color_type = PNG_COLOR_TYPE_PALETTE;
+ }
+ else
+ {
+ color_type = PNG_COLOR_TYPE_RGB;
+ }
+
+ png_set_IHDR(png_ptr, info_ptr, w, h,
+ 8, color_type, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ palette = png_malloc(png_ptr, sizeof(*palette) * 256);
+
+ /*
+ * TODO: Do we need to clean these bytes?
+ *
+ * memset(palette, 0, sizeof(*palette) * 256);
+ */
+
+ for (num = 0; num < 256 && color_table[num].found != 0; num++)
+ {
+ if (bitsPerPixel == 24)
+ {
+ palette[num].red = (color_table[num].pixel >> redShift) & redMax;
+ palette[num].green = (color_table[num].pixel >> greenShift) & greenMax;
+ palette[num].blue = color_table[num].pixel >> blueShift & blueMax;
+ }
+ else
+ {
+ int inRed, inGreen, inBlue;
+
+ inRed = (color_table[num].pixel >> redShift) & redMax;
+ inGreen = (color_table[num].pixel >> greenShift) & greenMax;
+ inBlue = color_table[num].pixel >> blueShift & blueMax;
+
+ palette[num].red = (CARD8)((inRed * 255 + redMax / 2) / redMax);
+ palette[num].green = (CARD8)((inGreen * 255 + greenMax / 2) / greenMax);
+ palette[num].blue = (CARD8)((inBlue * 255 + blueMax / 2) / blueMax);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressData: pixel[%d] r[%d] g[%d] b[%d].\n",
+ (int) color_table[num].pixel,palette[num].red,palette[num].green,palette[num].blue);
+ #endif
+ }
+
+ png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Setting palette.\n");
+ #endif
+ }
+
+ /*
+ * End of palette.
+ */
+
+ png_write_info(png_ptr, info_ptr);
+
+ /*
+ * Allocate space for one line of
+ * the image, 3 bytes per pixel.
+ */
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Initialization finished.\n");
+ #endif
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Error while writing the image rows.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ srcBuf = (CARD8 *) malloc(w * sizeof(CARD8));
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ (int) (w * sizeof(CARD8)));
+ #endif
+
+ return NULL;
+ }
+
+ /*
+ * TODO: Be sure the padded bytes are cleaned.
+ * It would be better to set to zero the bytes
+ * that are not alligned to the word boundary
+ * at the end of the procedure.
+ */
+
+ memset(srcBuf, 0, w * sizeof(CARD8));
+ }
+ else
+ {
+ srcBuf = (CARD8 *) malloc(w * 3 * sizeof(CARD8));
+
+ /*
+ * TODO: See above.
+ */
+
+ memset(srcBuf, 0, w * 3 * sizeof(CARD8));
+ }
+
+ if (srcBuf == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! Cannot allocate [%d] bytes.\n",
+ w * 3);
+ #endif
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ for (dy = 0; dy < h; dy++)
+ {
+ if (color_type == PNG_COLOR_TYPE_RGB)
+ {
+ PrepareRowForPng(srcBuf, dy, w);
+ }
+ else
+ {
+ memcpy(srcBuf, image_index + (dy * w), w);
+ }
+
+ png_write_row(png_ptr, srcBuf);
+ }
+
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: Compression finished. Lines handled [%d,%d].\n",
+ dy, h);
+ #endif
+
+ free(srcBuf);
+ free(image_index);
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******PngCompressData: PANIC! error during end of write.\n");
+ #endif
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+
+ png_write_end(png_ptr, NULL);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_free(png_ptr, palette);
+ }
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ /*
+ * Check the size of the resulting data.
+ */
+
+ if (pngDataLen > 0)
+ {
+ #ifdef DEBUG
+
+ int i = 0;
+
+ fprintf(stderr, "******PngCompressedData: Compressed size [%d].\n",
+ pngDataLen);
+
+ pngId++;
+ sprintf(pngName, "png%d", pngId);
+ pngFile = fopen(pngName, "w");
+
+ for (i = 0; i < pngDataLen; i++)
+ {
+ fprintf(pngFile, "%c", *(pngCompBuf + i));
+ }
+
+ fclose(pngFile);
+
+ #endif
+
+ *compressed_size = pngDataLen;
+
+ return pngCompBuf;
+ }
+ else
+ {
+ #ifdef DEBUG
+ fprintf(stderr, "******PngCompressedData: PANIC! Invalid size of the compressed data [%d].\n",
+ pngDataLen);
+ #endif
+
+ free(pngCompBuf);
+
+ return NULL;
+ }
+}
+
+static void PngWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ memcpy(((char *) png_get_io_ptr(png_ptr) + pngDataLen), data, length);
+
+ pngDataLen += length;
+}
+
+static void PngFlushData(png_structp png_ptr)
+{
+}
+
+void PrepareRowForPng(CARD8 *dst, int y, int count)
+{
+ if (bitsPerPixel == 32)
+ {
+ if (redMax == 0xff &&
+ greenMax == 0xff &&
+ blueMax == 0xff)
+ {
+ PrepareRowForPng24(dst, y, count);
+ }
+ else
+ {
+ PrepareRowForPng32(dst, y, count);
+ }
+ }
+ else if (bitsPerPixel == 24)
+ {
+ memcpy(dst, pngBeforeBuf + y * bytesPerLine, count * 3);
+ }
+ else
+ {
+ /*
+ * 16 bpp assumed.
+ */
+
+ PrepareRowForPng16(dst, y, count);
+ }
+}
+
+
+
+void PrepareRowForPng24(CARD8 *dst, int y, int count)
+{
+ CARD8 *fbptr;
+ CARD32 pix;
+
+ fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine);
+
+ while (count--)
+ {
+ if (byteOrder == LSBFirst)
+ {
+ pix = (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr+1);
+ pix = (pix << 8) | (CARD32) *fbptr;
+ }
+ else
+ {
+ pix = (CARD32) *(fbptr + 1);
+ pix = (pix << 8) | (CARD32) *(fbptr + 2);
+ pix = (pix << 8) | (CARD32) *(fbptr + 3);
+ }
+
+ *dst++ = (CARD8)(pix >> redShift);
+ *dst++ = (CARD8)(pix >> greenShift);
+ *dst++ = (CARD8)(pix >> blueShift);
+
+ fbptr+=4;
+ }
+}
+
+#define DEFINE_PNG_GET_ROW_FUNCTION(bpp) \
+ \
+void PrepareRowForPng##bpp(CARD8 *dst, int y, int count) \
+{ \
+ CARD8 *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ int i; \
+ \
+ fbptr = (CARD8 *) (pngBeforeBuf + y * bytesPerLine); \
+ \
+ while (count--) \
+ { \
+ pix = 0; \
+ \
+ if (byteOrder == LSBFirst) \
+ { \
+ for (i = (bpp >> 3) - 1; i >= 0; i--) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ else \
+ { \
+ for (i = 0; i < (bpp >> 3); i++) \
+ { \
+ pix = (pix << 8) | (CARD32) *(fbptr + i); \
+ } \
+ } \
+ \
+ fbptr += (bpp >> 3); \
+ \
+ inRed = (int) \
+ (pix >> redShift & redMax); \
+ inGreen = (int) \
+ (pix >> greenShift & greenMax); \
+ inBlue = (int) \
+ (pix >> blueShift & blueMax); \
+ *dst++ = (CARD8)((inRed * 255 + redMax / 2) / \
+ redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + greenMax / 2) / \
+ greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + blueMax / 2) / \
+ blueMax); \
+ } \
+}
+
+DEFINE_PNG_GET_ROW_FUNCTION(16)
+DEFINE_PNG_GET_ROW_FUNCTION(32)
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h
new file mode 100644
index 000000000..0e0621627
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Png.h
@@ -0,0 +1,76 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Png_H
+#define Png_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nx-X11/X.h>
+#include <nx-X11/Xlib.h>
+#include <nx-X11/Xmd.h>
+
+#include <png.h>
+
+extern int PngCompareColorTable(
+#if NeedFunctionPrototypes
+ NXColorTable* /* color_table_1 */,
+ NXColorTable* /* color_table_2 */
+#endif
+);
+
+extern char *PngCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ int* /* compressed_size */
+#endif
+);
+
+int NXCreatePalette16(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ CARD8* /* image_index */,
+ int /* nb_max */
+#endif
+);
+
+int NXCreatePalette32(
+#if NeedFunctionPrototypes
+ XImage* /* src_image */,
+ NXColorTable* /* color_table */,
+ CARD8* /* image_index */,
+ int /* nb_max */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Png_H */
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c
new file mode 100644
index 000000000..fc53ded92
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.c
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Rgb.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define RGB_COMPRESSION_LEVEL 4
+#define RGB_COMPRESSION_THRESHOLD 32
+#define RGB_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int rgbCompressionLevel = RGB_COMPRESSION_LEVEL;
+static int rgbCompressionThreshold = RGB_COMPRESSION_THRESHOLD;
+static int rgbCompressionStrategy = RGB_COMPRESSION_STRATEGY;
+
+char *RgbCompressData(XImage *image, unsigned int *size)
+{
+ return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
+ rgbCompressionThreshold, rgbCompressionLevel,
+ rgbCompressionStrategy, size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h
new file mode 100644
index 000000000..fd53ffbf9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rgb.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Rgb_H
+#define Rgb_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *RgbCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Rgb_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c
new file mode 100644
index 000000000..3f1da0de4
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.c
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Rle.h"
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define RLE_COMPRESSION_LEVEL 1
+#define RLE_COMPRESSION_THRESHOLD 32
+#define RLE_COMPRESSION_STRATEGY Z_RLE
+
+static int rleCompressionLevel = RLE_COMPRESSION_LEVEL;
+static int rleCompressionThreshold = RLE_COMPRESSION_THRESHOLD;
+static int rleCompressionStrategy = RLE_COMPRESSION_STRATEGY;
+
+char *RleCompressData(XImage *image, unsigned int *size)
+{
+ return ZCompressData(image -> data, image -> bytes_per_line * image -> height,
+ rleCompressionThreshold, rleCompressionLevel,
+ rleCompressionStrategy, size);
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h
new file mode 100644
index 000000000..a32812657
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h
@@ -0,0 +1,44 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Rle_H
+#define Rle_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *RleCompressData(
+#if NeedFunctionPrototypes
+ XImage* /* image */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Rle_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c
new file mode 100644
index 000000000..6ee08e236
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.c
@@ -0,0 +1,309 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <zlib.h>
+
+#include "Compext.h"
+
+#include "Z.h"
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#define Z_COMPRESSION_LEVEL 4
+#define Z_COMPRESSION_THRESHOLD 32
+#define Z_COMPRESSION_STRATEGY Z_DEFAULT_STRATEGY
+
+static int zCompressionLevel = Z_COMPRESSION_LEVEL;
+static int zCompressionStrategy = Z_COMPRESSION_STRATEGY;
+
+static z_stream *zStream;
+
+static int zInitialized;
+
+static int ZConfigure(int level, int strategy);
+
+static int ZDeflate(char *dest, unsigned int *destLen,
+ const char *source, unsigned int sourceLen);
+
+char *ZCompressData(const char *plainData, unsigned int plainSize, int threshold,
+ int level, int strategy, unsigned int *compressedSize)
+{
+ char *compressedData;
+
+ /*
+ * Determine the size of the source image
+ * data and make sure there is enough
+ * space in the destination buffer.
+ */
+
+ *compressedSize = plainSize + (plainSize / 1000) + 12 + 1;
+
+ compressedData = Xmalloc(*compressedSize);
+
+ if (compressedData == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZCompressData: PANIC! Failed to allocate [%d] bytes for the destination.\n",
+ *compressedSize);
+ #endif
+
+ *compressedSize = 0;
+
+ return NULL;
+ }
+
+ if (level == Z_NO_COMPRESSION || plainSize < threshold)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******ZCompressData: Not compressing [%d] bytes with level [%d] and "
+ "threshold [%d].\n", plainSize, level, threshold);
+ #endif
+
+ /*
+ * Tell in the first byte of the buffer
+ * if the remaining data is compressed
+ * or not. This same byte can be used
+ * in future to store some other flag.
+ */
+
+ *compressedData = 0;
+
+ memcpy(compressedData + 1, plainData, plainSize);
+
+ *compressedSize = plainSize + 1;
+
+ return compressedData;
+ }
+ else
+ {
+ int result;
+
+ /*
+ * Reconfigure the stream if needed.
+ */
+
+ if (zCompressionLevel != level ||
+ zCompressionStrategy != strategy)
+ {
+ ZConfigure(level, strategy);
+
+ zCompressionLevel = level;
+ zCompressionStrategy = strategy;
+ }
+
+ result = ZDeflate(compressedData + 1, compressedSize, plainData, plainSize);
+
+ if (result != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZCompressData: PANIC! Failed to compress [%d] bytes with error [%s].\n",
+ plainSize, zError(result));
+ #endif
+
+ Xfree(compressedData);
+
+ *compressedSize = 0;
+
+ return NULL;
+ }
+
+ #ifdef TEST
+ fprintf(stderr, "******ZCompressData: Source data of [%d] bytes compressed to [%d].\n",
+ plainSize, *compressedSize);
+ #endif
+
+ *compressedData = 1;
+
+ *compressedSize = *compressedSize + 1;
+
+ return compressedData;
+ }
+}
+
+int ZConfigure(int level, int strategy)
+{
+ /*
+ * ZLIB wants the avail_out to be
+ * non zero, even if the stream was
+ * already flushed.
+ */
+
+ unsigned char dest[1];
+
+ zStream -> next_out = dest;
+ zStream -> avail_out = 1;
+
+ if (deflateParams(zStream, level, strategy) != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZConfigure: PANIC! Failed to set level to [%d] and strategy to [%d].\n",
+ level, strategy);
+ #endif
+
+ return -1;
+ }
+ #ifdef TEST
+ else
+ {
+ fprintf(stderr, "******ZConfigure: Reconfigured the stream with level [%d] and strategy [%d].\n",
+ level, strategy);
+ }
+ #endif
+
+ return 1;
+}
+
+int ZDeflate(char *dest, unsigned int *destLen, const char *source, unsigned int sourceLen)
+{
+ int saveOut;
+ int result;
+
+ /*
+ * Deal with the possible overflow.
+ */
+
+ if (zStream -> total_out & 0x80000000)
+ {
+ #ifdef TEST
+ fprintf(stderr, "******ZDeflate: Reset Z stream counters with total in [%ld] total out [%ld].\n",
+ zStream -> total_in, zStream -> total_out);
+ #endif
+
+ zStream -> total_in = 0;
+ zStream -> total_out = 0;
+ }
+
+ saveOut = zStream -> total_out;
+
+ zStream -> next_in = (Bytef *) source;
+ zStream -> avail_in = (uInt) sourceLen;
+
+ #ifdef MAXSEG_64K
+
+ /*
+ * Check if the source is greater
+ * than 64K on a 16-bit machine.
+ */
+
+ if ((uLong) zStream -> avail_in != sourceLen) return Z_BUF_ERROR;
+
+ #endif
+
+ zStream -> next_out = (unsigned char *) dest;
+ zStream -> avail_out = (uInt) *destLen;
+
+ if ((uLong) zStream -> avail_out != *destLen) return Z_BUF_ERROR;
+
+ result = deflate(zStream, Z_FINISH);
+
+ if (result != Z_STREAM_END)
+ {
+ deflateReset(zStream);
+
+ return (result == Z_OK ? Z_BUF_ERROR : result);
+ }
+
+ *destLen = zStream -> total_out - saveOut;
+
+ result = deflateReset(zStream);
+
+ return result;
+}
+
+int ZInitEncoder()
+{
+ if (zInitialized == 0)
+ {
+ int result;
+
+ zStream = Xmalloc(sizeof(z_stream));
+
+ if (zStream == NULL)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZInitEncoder: PANIC! Failed to allocate memory for the stream.\n");
+ #endif
+
+ return -1;
+ }
+
+ zStream -> zalloc = (alloc_func) 0;
+ zStream -> zfree = (free_func) 0;
+ zStream -> opaque = (voidpf) 0;
+
+ #ifdef TEST
+ fprintf(stderr, "******ZInitEncoder: Initializing compressor with level [%d] and startegy [%d].\n",
+ zCompressionLevel, zCompressionStrategy);
+ #endif
+
+ result = deflateInit2(zStream, zCompressionLevel, Z_DEFLATED,
+ 15, 9, zCompressionStrategy);
+
+ if (result != Z_OK)
+ {
+ #ifdef PANIC
+ fprintf(stderr, "******ZInitEncoder: Failed to initialize the compressor with error [%s].\n",
+ zError(result));
+ #endif
+
+ return -1;
+ }
+
+ zInitialized = 1;
+ }
+
+ return zInitialized;
+}
+
+int ZResetEncoder()
+{
+ int result;
+
+ if (zInitialized == 1)
+ {
+ result = deflateEnd(zStream);
+
+ if (result != Z_OK)
+ {
+ #ifdef WARNING
+ fprintf(stderr, "******ZResetEncoder: WARNING! Failed to deinitialize the compressor with error [%s].\n",
+ zError(result));
+ #endif
+ }
+
+ Xfree(zStream);
+ }
+
+ zInitialized = 0;
+
+ return 1;
+}
diff --git a/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h
new file mode 100644
index 000000000..8133f0c73
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/compext/Z.h
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXCOMPEXT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#ifndef Z_H
+#define Z_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int ZInitEncoder(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+
+int ZResetEncoder(
+#if NeedFunctionPrototypes
+void
+#endif
+);
+
+extern char *ZCompressData(
+#if NeedFunctionPrototypes
+ const char* /* data */,
+ unsigned int /* size */,
+ int /* threshold */,
+ int /* level */,
+ int /* strategy */,
+ unsigned int* /* compressed_size */
+#endif
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* Z_H */
diff --git a/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1 b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1
new file mode 100644
index 000000000..1abec5753
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/man/nxagent.1
@@ -0,0 +1,1050 @@
+
+.\" Copyright 1984 - 1991, 1993, 1994, 1998 The Open Group
+.\" Copyright 2011 - 2016, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
+.\"
+.\" 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.
+.\"
+.\" 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 THE OPEN GROUP 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.
+.\"
+.\" Except as contained in this notice, the name of The Open Group shall
+.\" not be used in advertising or otherwise to promote the sale, use or
+.\" other dealings in this Software without prior written authorization
+.\" from The Open Group.
+.ds q \N'34'
+.TH nxagent 1 "April 2017" "Version 3.6.x" "NX Agent (Xserver)"
+.SH NAME
+nxagent \- nested Xserver optimized for remote computing
+.SH SYNOPSIS
+.B nxagent
+.I "[options]"
+.SH DESCRIPTION
+\fBnxagent\fR is an X server for remote application/desktop access
+similar to Xnest or Xephyr.
+.PP
+\fBnxagent\fR implements a very efficient compression of the X11
+protocol, called the NX protocol.
+.PP
+The NX protocol increases performance when using X applications over high
+latency and low bandwidth networks, while providing a local (LAN-like)
+usage experience even if connecting from off-site locations (via cable
+modem or GSM).
+.PP
+\fBnxagent\fR can be used standalone as a nested X server (with NX
+protocol disabled), but its real benefits are gained when using it over
+remote connections via the nxcomp compression library. The counterpart
+application on the other end (i.e. the client) is called
+\fBnxproxy\fR.
+.PP
+When used in proxy <-> agent mode, \fBnxagent\fR adds the feature of
+being suspendible. Sessions can be started from one client, suspended and
+then resumed from another (or the same) client.
+.PP
+\fBnxagent\fR and \fBnxproxy\fR are utilized by various remote
+application/desktop frameworks for providing server-side GUI application
+access from remote client systems.
+.PP
+Currently, \fBnxagent\fR is co-maintained by three of these projects: The
+Arctica Project, TheQVD and X2Go.
+.PP
+
+.SH "STARTING THE SERVER"
+\fBnxagent\fR should be run in user space. Other than the system's
+local X.org server, \fBnxagent\fR does not require to be run as root.
+When bundled with a remote application framework, you normally don't have
+to launch \fBnxagent\fR manually. \fBnxagent\fR startup is usually
+managed by the underlying framework (e.g. Arctica Session Manager, X2Go
+Server, etc.).
+.PP
+When \fBnxagent\fR starts up (e.g. by typing 'nxagent -ac :1' in a
+terminal window), it typically launches in "windowed desktop" mode. On
+your local X server a new window appears being an X server itself.
+.PP
+However, \fBnxagent\fR also supports rootless (or seamless) application
+mode and a shadow session mode (similar to what VNC does).
+.PP
+Example: You can launch a complete desktop session inside this nested X
+server now:
+.TP 8
+The Debian way...
+.PP
+.nf
+ $ export DISPLAY=:1
+ $ STARTUP=mate-session /etc/X11/Xsession
+.fi
+.TP 8
+The Fedora / Gentoo / openSUSE way...
+.PP
+.nf
+ ### FIXME / TODO ###
+.fi
+.PP
+However, \fBnxagent\fR also supports rootless (or seamless) application
+mode and a shadow session mode (similar to what VNC does).
+
+.SH OPTIONS
+\fBnxagent\fR accepts a range of default X server options as described
+below. Those default options have to be provided via the command line.
+
+Furthermore, \fBnxagent\fR accepts some nx-X11 specific options,
+described further below.
+
+Last but not least, \fBnxagent\fR accepts several more options, the
+so-called nx/nx options, provided via the $DISPLAY environment
+variable or the -options command line option. See below for further
+details.
+
+.SH STANDARD XSERVER OPTIONS
+.TP 8
+.B :\fIdisplaynumber\fP
+The X server runs as the given \fIdisplaynumber\fP, which by default is 0.
+If multiple X servers are to run simultaneously on a host, each must have
+a unique display number. See the DISPLAY
+NAMES section of the \fIX\fP(__miscmansuffix__) manual page to learn how to
+specify which display number clients should try to use.
+.TP 8
+.B \-a \fInumber\fP
+sets pointer acceleration (i.e. the ratio of how much is reported to how much
+the user actually moved the pointer).
+.TP 8
+.B \-ac
+disables host-based access control mechanisms. Enables access by any host,
+and permits any host to modify the access control list.
+Use with extreme caution.
+This option exists primarily for running test suites remotely.
+.TP 8
+.B \-audit \fIlevel\fP
+sets the audit trail level. The default level is 1, meaning only connection
+rejections are reported. Level 2 additionally reports all successful
+connections and disconnects. Level 4 enables messages from the
+SECURITY extension, if present, including generation and revocation of
+authorizations and violations of the security policy.
+Level 0 turns off the audit trail.
+Audit lines are sent as standard error output.
+.TP 8
+.B \-auth \fIauthorization-file\fP
+specifies a file which contains a collection of authorization records used
+to authenticate access. See also the \fIxdm\fP(1) and
+\fIXsecurity\fP(__miscmansuffix__) manual pages.
+.TP 8
+.B bc
+disables certain kinds of error checking, for bug compatibility with
+previous releases (e.g., to work around bugs in R2 and R3 xterms and toolkits).
+Deprecated.
+.TP 8
+.B \-bs
+disables backing store support on all screens.
+.TP 8
+.B \-br
+sets the default root window to solid black instead of the standard root weave
+pattern.
+.TP 8
+.B \-c
+turns off key-click.
+.TP 8
+.B c \fIvolume\fP
+sets key-click volume (allowable range: 0-100).
+.TP 8
+.B \-cc \fIclass\fP
+sets the visual class for the root window of color screens.
+The class numbers are as specified in the X protocol.
+Not obeyed by all servers.
+.ig
+.TP 8
+.B \-config \fIfilename\fP
+reads more options from the given file. Options in the file may be separated
+by newlines if desired. If a '#' character appears on a line, all characters
+between it and the next newline are ignored, providing a simple commenting
+facility. The \fB\-config\fP option itself may appear in the file.
+.BR NOTE :
+This option is disabled when the Xserver is run with an effective uid
+different from the user's real uid.
+..
+.TP 8
+.B \-core
+causes the server to generate a core dump on fatal errors.
+.TP 8
+.B \-displayfd \fIfd\fP
+specifies a file descriptor in the launching process. Rather than specifying
+a display number, the X server will attempt to listen on successively higher
+display numbers, and upon finding a free one, will write the port number back
+on this file descriptor as a newline-terminated string. The \fB\-pn\fR option is
+ignored when using \fB\-displayfd\fR.
+
+nxagent specific:
+
+(1) Other than in X.org's Xserver, you can use \fB\-displayfd\fR in
+conjunction with an explicit display number. If the explicit display number
+is not available (i.e., already in use), nxagent tries to figure out the next
+available display number,
+
+e.g.:
+
+ \fBnxagent\fR \fI\-displayfd 2 :50\fR
+
+(2) If -displayfd <X> is given with <X> equaling 2 (STDERR), then the
+display number string written to STDERR is beautified with some human-readable
+(machine-parseable) text.
+.TP 8
+.B \-deferglyphs \fIwhichfonts\fP
+specifies the types of fonts for which the server should attempt to use
+deferred glyph loading. \fIwhichfonts\fP can be all (all fonts),
+none (no fonts), or 16 (16 bit fonts only).
+.TP 8
+.B \-dpi \fIresolution\fP
+sets the resolution for all screens, in dots per inch.
+To be used when the server cannot determine the screen size(s) from the
+hardware.
+.TP 8
+.B dpms
+enables DPMS (display power management services), where supported. The
+default state is platform and configuration specific.
+.TP 8
+.B \-dpms
+disables DPMS (display power management services). The default state
+is platform and configuration specific.
+.TP 8
+.B \-f \fIvolume\fP
+sets feep (bell) volume (allowable range: 0-100).
+.TP 8
+.B \-fc \fIcursorFont\fP
+sets default cursor font.
+.TP 8
+.B \-fn \fIfont\fP
+sets the default font.
+.TP 8
+.B \-fp \fIfontPath\fP
+sets the search path for fonts. This path is a comma separated list
+of directories which the X server searches for font databases.
+See the FONTS section of this manual page for more information and the default
+list.
+.TP 8
+.B \-help
+prints a usage message.
+.TP 8
+.B \-I
+causes all remaining command line arguments to be ignored.
+.TP 8
+.B \-maxbigreqsize \fIsize\fP
+sets the maximum big request to
+.I size
+MB.
+.TP 8
+.B \-nolisten \fItrans-type\fP
+disables a transport type. For example, TCP/IP connections can be disabled
+with
+.BR "\-nolisten tcp" .
+This option may be issued multiple times to disable listening to different
+transport types.
+.TP 8
+.B \-noreset
+prevents a server reset when the last client connection is closed. This
+overrides a previous
+.B \-terminate
+command line option.
+.TP 8
+.B \-p \fIminutes\fP
+sets screen-saver pattern cycle time in minutes.
+.TP 8
+.B \-pn
+permits the server to continue running if it fails to establish all of
+its well-known sockets (connection points for clients), but
+establishes at least one. This option is set by default.
+.TP 8
+.B \-nopn
+causes the server to exit if it fails to establish all of its well-known
+sockets (connection points for clients).
+.TP 8
+.B \-r
+turns off auto-repeat.
+.TP 8
+.B r
+turns on auto-repeat.
+.TP 8
+.B \-s \fIminutes\fP
+sets screen-saver timeout time in minutes.
+.TP 8
+.B \-su
+disables save under support on all screens.
+.TP 8
+.B \-t \fInumber\fP
+sets pointer acceleration threshold in pixels (i.e. after how many pixels
+pointer acceleration should take effect).
+.TP 8
+.B \-terminate
+causes the server to terminate at server reset, instead of continuing to run.
+This overrides a previous
+.B \-noreset
+command line option.
+.TP 8
+.B \-to \fIseconds\fP
+sets default connection timeout in seconds.
+.TP 8
+.B \-tst
+disables all testing extensions.
+.TP 8
+.B tty\fIxx\fP
+ignored, for servers started the ancient way (from init).
+.TP 8
+.B v
+sets video-off screen-saver preference.
+.TP 8
+.B \-v
+sets video-on screen-saver preference.
+.TP 8
+.B \-wm
+forces the default backing-store of all windows to be WhenMapped. This
+is a backdoor way of getting backing-store to apply to all windows.
+Although all mapped windows will have backing store, the backing store
+attribute value reported by the server for a window will be the last
+value established by a client. If it has never been set by a client,
+the server will report the default value, NotUseful. This behavior is
+required by the X protocol, which allows the server to exceed the
+client's backing store expectations but does not provide a way to tell
+the client that it is doing so.
+.TP 8
+.B [+-]xinerama
+enables(+) or disables(-) XINERAMA provided via the PanoramiX extension. This is
+set to off by default.
+.TP 8
+.B [+-]rrxinerama
+enables(+) or disables(-) XINERAMA provided via the RandR extension. By
+default, this feature is enabled. To disable XINERAMA completely, make
+sure to use both options (-xinerama -rrxinerama) on the command line.
+
+.SH SERVER DEPENDENT OPTIONS
+\fBnxagent\fR additionally accepts the following non-standard options:
+.TP 8
+.B \-logo
+turns on the X Window System logo display in the screen-saver.
+There is currently no way to change this from a client.
+.TP 8
+.B nologo
+turns off the X Window System logo display in the screen-saver.
+There is currently no way to change this from a client.
+.TP 8
+.B \-render
+
+.BR default | mono | gray | color
+
+sets the color allocation policy that will be used by the render extension.
+.RS 8
+.TP 8
+.I default
+selects the default policy defined for the display depth of the X
+server.
+.TP 8
+.I mono
+don't use any color cell.
+.TP 8
+.I gray
+use a gray map of 13 color cells for the X render extension.
+.TP 8
+.I color
+use a color cube of at most 4*4*4 colors (that is 64 color cells).
+.RE
+.TP 8
+.B \-dumbSched
+disables smart scheduling on platforms that support the smart scheduler.
+.TP
+.B \-schedInterval \fIinterval\fP
+sets the smart scheduler's scheduling interval to
+.I interval
+milliseconds.
+.SH NXAGENT SPECIFIC OPTIONS
+The nx-X11 system adds the following command line arguments:
+.TP 8
+.B \-forcenx
+force use of NX protocol messages assuming communication through nxproxy
+.TP 8
+.B \-timeout \fIint\fP
+auto-disconnect timeout in seconds (minimum allowed: 60)
+.TP 8
+.B \-norootlessexit
+don't exit if there are no clients in rootless mode
+.TP 8
+.B \-norender
+disable the use of the render extension
+.TP 8
+.B \-nocomposite
+disable the use of the composite extension
+.TP 8
+.B \-nopersistent
+disable disconnection/reconnection to the X display on SIGHUP
+.TP 8
+.B \-noshmem
+disable use of shared memory extension
+.TP 8
+.B \-shmem
+enable use of shared memory extension
+.TP 8
+.B \-noshpix
+disable use of shared pixmaps
+.TP 8
+.B \-shpix
+enable use of shared pixmaps
+.TP 8
+.B \-noignore
+don't ignore pointer and keyboard configuration changes mandated by clients
+.TP 8
+.B \-nokbreset
+don't reset keyboard device if the session is resumed
+.TP 8
+.B \-noxkblock
+always allow applications to change layout through XKEYBOARD
+.TP 8
+.B \-tile WxH
+size of image tiles (minimum allowed: 32x32)
+.TP 8
+.B \-D
+enable desktop mode (default)
+.TP 8
+.B \-R
+enable rootless mode
+.TP 8
+.B \-S
+enable shadow mode
+.TP 8
+.B \-B
+enable proxy binding mode
+.TP 8
+.B \-options \fIfilename\fP
+path to an options file containing nx/nx options (see below).
+.PP
+Other than the command line options, \fBnxagent\fR can be configured at
+session startup and at runtime (i.e. when resuming a suspended session)
+by so-called nx/nx options.
+.PP
+As nx/nx options all options supported by nxcomp (see \fBnxproxy\fR man
+page) and all \fBnxagent\fR nx/nx options (see below) can be used.
+.
+When launching an nxcomp based \fBnxagent\fR session (i.e. proxy <->
+agent), you will normally set the $DISPLAY variable like this:
+.PP
+.nf
+ $ export DISPLAY=nx/nx,listen=<proxy-port>,options=<options.file>:<nx-display-port>
+ $ nxagent <cmdline-options> :<nx-display-port>
+.fi
+.PP
+The value for <nx-display-port> is some value of a not-yet-used X11
+display (e.g. :50).
+.PP
+Using an options file is recommended, but you can also put available
+nx/nx options (see below) into the DISPLAY variable directly. Note, that
+the $DISPLAY variable field is of limited length.
+.PP
+As <proxy-port> you can pick an arbitrary (unused) TCP port or Unix
+socket file path. This is the port / socket that you have to connect to
+with the \fBnxproxy\fR application.
+.PP
+Available \fBnxagent\fR options (as an addition to nx/nx options supported
+by nxcomp already):
+.TP 8
+.B options=<string>
+read options from file, this text file can contain a single loooong line with comma-separated nx/nx options
+.TP 8
+.B rootless=<bool>
+start \fBnxagent\fR in rootless mode, matches \-R given on the command line, no-op when resuming (default: false)
+.TP 8
+.B geometry=<string>
+desktop geometry when starting or resuming a session, no-op in rootless mode (default 66% of the underlying X server geometry)
+.TP 8
+.B resize=<bool>
+set resizing support (default: true)
+.TP 8
+.B fullscreen=<bool>
+start or resume a session in fullscreen mode (default: off)
+.TP 8
+.B keyboard=<string>
+set remote keyboard layout
+.TP 8
+.B clipboard=<string>
+
+.BR both | client | server | none
+
+enable / disable (set to: \fInone\fR) clipboard support, uni-directional (\fIserver\fR or \fIclient\fR) or bi-directional (\fIboth\fR, default setting) support
+.TP 8
+.B streaming=<int>
+streaming support for images, not fully implemented yet and thus non-functional
+.TP 8
+.B backingstore=<int>
+disable or enforce backing store support (default: BackingStoreUndefined)
+.TP 8
+.B composite=<int>
+enable or disable Compsite support in \fBnxagent\fR (default: enabled)
+.TP 8
+.B xinerama=<int>
+enable or disable XINERAMA support in \fBnxagent\fR (default: enabled)
+.TP 8
+.B shmem=<bool>
+enable using shared memory
+.TP 8
+.B shpix=<bool>
+enable shared pixmaps support
+.TP 8
+.B kbtype=<string>
+set remote keyboard type
+.TP 8
+.B client=<string>
+type of connecting operating system (supported: \fIlinux\fR, \fIwindows\fR, \fIsolaris\fR and \fImacosx\fR)
+.TP 8
+.B shadow=<int>
+start \fBnxagent\fR in shadow mode, matches \-S given on the command line, no-op when resuming (default: false)
+.TP 8
+.B shadowuid=<int>
+unique identifier for the shadow session
+.TP 8
+.B shadowmode=<string>
+full access (set to \fI1\fR) or viewing-only (set to \fI0\fR, default)
+.TP 8
+.B defer=<int>
+defer image updates (enabled for all connection types except LAN), accepts values \fI0\fR, \fI1\fR and \fI2\fR
+
+The default value can be set via the cmd line (\-defer). The value
+provided as nx/nx option is set when resuming a session, thus it
+overrides the cmd line default.
+.TP 8
+.B tile=<string>
+set the tile size in pixels (\fI<W>x<H>\fR) for bitmap data sent over the wire
+
+The default value can be set via the cmd line (\-tile). The value
+provided as nx/nx option is set when resuming a session, thus it
+overrides the cmd line default.
+.TP 8
+.B menu=<int>
+support pulldown menu in \fBnxagent\fR session (only available on proxy <-> agent remote sessions)
+.TP 8
+.B sleep=<int>
+delay X server operations when suspended (provided in msec), set to \fI0\fR to keep \fBnxagent\fR session
+fully functional when suspended (e.g. useful when mirroring an \fBnxagent\fR session via VNC)
+.TP 8
+.B tolerancechecks=<string>
+
+.BR strict|safe|risky|bypass
+.RS 8
+.TP 8
+.I strict
+means that the number of internal and external pixmap formats must
+match exactly and every internal pixmap format must be available in the
+external pixmap format array. This is the default.
+.TP 8
+.I safe
+means that the number of pixmap formats might diverge, but all
+internal pixmap formats must also be included in the external pixmap
+formats array. This is recommended, because it allows clients with more
+pixmap formats to still connect, but not lose functionality.
+.TP 8
+.I risky
+means that the internal pixmap formats array is allowed to be
+smaller than the external pixmap formats array, but at least one pixmap
+format must be included in both. This is potentially unsafe.
+.TP 8
+.I bypass
+means that all of these checks are essentially
+deactivated. This is a very bad idea.
+.RE
+
+If you want to use \fBnxagent\fR as a replacement for Xnest or Xephyr you
+can pass options like this:
+.PP
+.nf
+ $ echo nx/nx,fullscreen=1$DISPLAY >/tmp/opt
+ $ nxagent <cmdline-options> -options /tmp/opt :<nx-display-port>
+.fi
+
+.SH XDMCP OPTIONS
+X servers that support XDMCP have the following options.
+See the \fIX Display Manager Control Protocol\fP specification for more
+information.
+.TP 8
+.B \-query \fIhostname\fP
+enables XDMCP and sends Query packets to the specified
+.IR hostname .
+.TP 8
+.B \-broadcast
+enable XDMCP and broadcasts BroadcastQuery packets to the network. The
+first responding display manager will be chosen for the session.
+.TP 8
+.B \-multicast [\fIaddress\fP [\fIhop count\fP]]
+Enable XDMCP and multicast BroadcastQuery packets to the network.
+The first responding display manager is chosen for the session. If an
+address is specified, the multicast is sent to that address. If no
+address is specified, the multicast is sent to the default XDMCP IPv6
+multicast group. If a hop count is specified, it is used as the maximum
+hop count for the multicast. If no hop count is specified, the multicast
+is set to a maximum of 1 hop, to prevent the multicast from being routed
+beyond the local network.
+.TP 8
+.B \-indirect \fIhostname\fP
+enables XDMCP and send IndirectQuery packets to the specified
+.IR hostname .
+.TP 8
+.B \-port \fIport-number\fP
+uses the specified \fIport-number\fP for XDMCP packets, instead of the
+default. This option must be specified before any \-query, \-broadcast,
+\-multicast, or \-indirect options.
+.TP 8
+.B \-from \fIlocal-address\fP
+specifies the local address to connect from (useful if the connecting host
+has multiple network interfaces). The \fIlocal-address\fP may be expressed
+in any form acceptable to the host platform's \fIgethostbyname\fP(3)
+implementation.
+.TP 8
+.B \-once
+causes the server to terminate (rather than reset) when the XDMCP session
+ends.
+.TP 8
+.B \-class \fIdisplay-class\fP
+XDMCP has an additional display qualifier used in resource lookup for
+display-specific options. This option sets that value, by default it
+is "MIT-Unspecified" (not a very useful value).
+.TP 8
+.B \-cookie \fIxdm-auth-bits\fP
+When testing XDM-AUTHENTICATION-1, a private key is shared between the
+server and the manager. This option sets the value of that private
+data (not that it is very private, being on the command line!).
+.TP 8
+.B \-displayID \fIdisplay-id\fP
+Yet another XDMCP specific value, this one allows the display manager to
+identify each display so that it can locate the shared key.
+
+.SH XKEYBOARD OPTIONS
+X servers that support the XKEYBOARD (a.k.a. \*qXKB\*q) extension accept the
+following options. All layout files specified on the command line must be
+located in the XKB base directory or a subdirectory, and specified as the
+relative path from the XKB base directory. The default XKB base directory is
+.IR /usr/share/X11/xkb .
+.TP 8
+.B [+-]kb
+enables(+) or disables(-) the XKEYBOARD extension.
+.TP 8
+.BR [+-]accessx " [ \fItimeout\fP [ \fItimeout_mask\fP [ \fIfeedback\fP [ \fIoptions_mask\fP ] ] ] ]"
+enables(+) or disables(-) AccessX key sequences.
+.TP 8
+.B \-xkbdir \fIdirectory\fP
+base directory for keyboard layout files. This option is not available
+for setuid X servers (i.e., when the X server's real and effective uids
+are different).
+.TP 8
+.B \-ar1 \fImilliseconds\fP
+sets the autorepeat delay (length of time in milliseconds that a key must
+be depressed before autorepeat starts).
+.TP 8
+.B \-ar2 \fImilliseconds\fP
+sets the autorepeat interval (length of time in milliseconds that should
+elapse between autorepeat-generated keystrokes).
+.TP 8
+.B \-noloadxkb
+disables loading of an XKB keymap description on server startup.
+.TP 8
+.B \-xkbdb \fIfilename\fP
+uses \fIfilename\fP for default keyboard keymaps.
+.TP 8
+.B \-xkbmap \fIfilename\fP
+loads keyboard description in \fIfilename\fP on server startup.
+
+.SH SECURITY EXTENSION OPTIONS
+X servers that support the SECURITY extension accept the following option:
+.TP 8
+.B \-sp \fIfilename\fP
+causes the server to attempt to read and interpret filename as a security
+policy file with the format described below. The file is read at server
+startup and reread at each server reset.
+.PP
+The syntax of the security policy file is as follows.
+Notation: "*" means zero or more occurrences of the preceding element,
+and "+" means one or more occurrences. To interpret <foo/bar>, ignore
+the text after the /; it is used to distinguish between instances of
+<foo> in the next section.
+.PP
+.nf
+<policy file> ::= <version line> <other line>*
+
+<version line> ::= <string/v> '\en'
+
+<other line > ::= <comment> | <access rule> | <site policy> | <blank line>
+
+<comment> ::= # <not newline>* '\en'
+
+<blank line> ::= <space> '\en'
+
+<site policy> ::= sitepolicy <string/sp> '\en'
+
+<access rule> ::= property <property/ar> <window> <perms> '\en'
+
+<property> ::= <string>
+
+<window> ::= any | root | <required property>
+
+<required property> ::= <property/rp> | <property with value>
+
+<property with value> ::= <property/rpv> = <string/rv>
+
+<perms> ::= [ <operation> | <action> | <space> ]*
+
+<operation> ::= r | w | d
+
+<action> ::= a | i | e
+
+<string> ::= <dbl quoted string> | <single quoted string> | <unqouted string>
+
+<dbl quoted string> ::= <space> " <not dqoute>* " <space>
+
+<single quoted string> ::= <space> ' <not squote>* ' <space>
+
+<unquoted string> ::= <space> <not space>+ <space>
+
+<space> ::= [ ' ' | '\et' ]*
+
+Character sets:
+
+<not newline> ::= any character except '\en'
+<not dqoute> ::= any character except "
+<not squote> ::= any character except '
+<not space> ::= any character except those in <space>
+.fi
+.PP
+The semantics associated with the above syntax are as follows.
+.PP
+<version line>, the first line in the file, specifies the file format
+version. If the server does not recognize the version <string/v>, it
+ignores the rest of the file. The version string for the file format
+described here is "version-1" .
+.PP
+Once past the <version line>, lines that do not match the above syntax
+are ignored.
+.PP
+<comment> lines are ignored.
+.PP
+<sitepolicy> lines are currently ignored. They are intended to
+specify the site policies used by the XC-QUERY-SECURITY-1
+authorization method.
+.PP
+<access rule> lines specify how the server should react to untrusted
+client requests that affect the X Window property named <property/ar>.
+The rest of this section describes the interpretation of an
+<access rule>.
+.PP
+For an <access rule> to apply to a given instance of <property/ar>,
+<property/ar> must be on a window that is in the set of windows
+specified by <window>. If <window> is any, the rule applies to
+<property/ar> on any window. If <window> is root, the rule applies to
+<property/ar> only on root windows.
+.PP
+If <window> is <required property>, the following apply. If <required
+property> is a <property/rp>, the rule applies when the window also
+has that <property/rp>, regardless of its value. If <required
+property> is a <property with value>, <property/rpv> must also have
+the value specified by <string/rv>. In this case, the property must
+have type STRING and format 8, and should contain one or more
+null-terminated strings. If any of the strings match <string/rv>, the
+rule applies.
+.PP
+The definition of string matching is simple case-sensitive string
+comparison with one elaboration: the occurrence of the character '*' in
+<string/rv> is a wildcard meaning "any string." A <string/rv> can
+contain multiple wildcards anywhere in the string. For example, "x*"
+matches strings that begin with x, "*x" matches strings that end with
+x, "*x*" matches strings containing x, and "x*y*" matches strings that
+start with x and subsequently contain y.
+.PP
+There may be multiple <access rule> lines for a given <property/ar>.
+The rules are tested in the order that they appear in the file. The
+first rule that applies is used.
+.PP
+<perms> specify operations that untrusted clients may attempt, and
+the actions that the server should take in response to those operations.
+.PP
+<operation> can be r (read), w (write), or d (delete). The following
+table shows how X Protocol property requests map to these operations
+in The Open Group server implementation.
+.PP
+.nf
+GetProperty r, or r and d if delete = True
+ChangeProperty w
+RotateProperties r and w
+DeleteProperty d
+ListProperties none, untrusted clients can always list all properties
+.fi
+.PP
+<action> can be a (allow), i (ignore), or e (error). Allow means
+execute the request as if it had been issued by a trusted client.
+Ignore means treat the request as a no-op. In the case of
+GetProperty, ignore means return an empty property value if the
+property exists, regardless of its actual value. Error means do not
+execute the request and return a BadAtom error with the atom set to
+the property name. Error is the default action for all properties,
+including those not listed in the security policy file.
+.PP
+An <action> applies to all <operation>s that follow it, until the next
+<action> is encountered. Thus, irwad means ignore read and write,
+allow delete.
+.PP
+GetProperty and RotateProperties may do multiple operations (r and d,
+or r and w). If different actions apply to the operations, the most
+severe action is applied to the whole request; there is no partial
+request execution. The severity ordering is: allow < ignore < error.
+Thus, if the <perms> for a property are ired (ignore read, error
+delete), and an untrusted client attempts GetProperty on that property
+with delete = True, an error is returned, but the property value is
+not. Similarly, if any of the properties in a RotateProperties do not
+allow both read and write, an error is returned without changing any
+property values.
+.PP
+Here is an example security policy file.
+.PP
+.ta 3i 4i
+.nf
+version-1
+
+# Allow reading of application resources, but not writing.
+property RESOURCE_MANAGER root ar iw
+property SCREEN_RESOURCES root ar iw
+
+# Ignore attempts to use cut buffers. Giving errors causes apps to crash,
+# and allowing access may give away too much information.
+property CUT_BUFFER0 root irw
+property CUT_BUFFER1 root irw
+property CUT_BUFFER2 root irw
+property CUT_BUFFER3 root irw
+property CUT_BUFFER4 root irw
+property CUT_BUFFER5 root irw
+property CUT_BUFFER6 root irw
+property CUT_BUFFER7 root irw
+
+# If you are using Motif, you probably want these.
+property _MOTIF_DEFAULT_BINDINGS root ar iw
+property _MOTIF_DRAG_WINDOW root ar iw
+property _MOTIF_DRAG_TARGETS any ar iw
+property _MOTIF_DRAG_ATOMS any ar iw
+property _MOTIF_DRAG_ATOM_PAIRS any ar iw
+
+# The next two rules let xwininfo -tree work when untrusted.
+property WM_NAME any ar
+
+# Allow read of WM_CLASS, but only for windows with WM_NAME.
+# This might be more restrictive than necessary, but demonstrates
+# the <required property> facility, and is also an attempt to
+# say "top level windows only."
+property WM_CLASS WM_NAME ar
+
+# These next three let xlsclients work untrusted. Think carefully
+# before including these; giving away the client machine name and command
+# may be exposing too much.
+property WM_STATE WM_NAME ar
+property WM_CLIENT_MACHINE WM_NAME ar
+property WM_COMMAND WM_NAME ar
+
+# To let untrusted clients use the standard colormaps created by
+# xstdcmap, include these lines.
+property RGB_DEFAULT_MAP root ar
+property RGB_BEST_MAP root ar
+property RGB_RED_MAP root ar
+property RGB_GREEN_MAP root ar
+property RGB_BLUE_MAP root ar
+property RGB_GRAY_MAP root ar
+
+# To let untrusted clients use the color management database created
+# by xcmsdb, include these lines.
+property XDCCC_LINEAR_RGB_CORRECTION root ar
+property XDCCC_LINEAR_RGB_MATRICES root ar
+property XDCCC_GRAY_SCREENWHITEPOINT root ar
+property XDCCC_GRAY_CORRECTION root ar
+
+# To let untrusted clients use the overlay visuals that many vendors
+# support, include this line.
+property SERVER_OVERLAY_VISUALS root ar
+
+# Dumb examples to show other capabilities.
+
+# oddball property names and explicit specification of error conditions
+property "property with spaces" 'property with "' aw er ed
+
+# Allow deletion of Woo-Hoo if window also has property OhBoy with value
+# ending in "son". Reads and writes will cause an error.
+property Woo-Hoo OhBoy = "*son" ad
+
+.fi
+.SH "NETWORK CONNECTIONS"
+The X server supports client connections via a platform-dependent subset of
+the following transport types: TCP\/IP, Unix Domain sockets
+and several varieties of SVR4 local connections. See the DISPLAY
+NAMES section of the \fIX\fP(__miscmansuffix__) manual page to learn how to
+specify which transport type clients should try to use.
+
+.SH GRANTING ACCESS
+The X server implements a platform-dependent subset of the following
+authorization protocols: MIT-MAGIC-COOKIE-1, XDM-AUTHORIZATION-1,
+XDM-AUTHORIZATION-2, SUN-DES-1, and MIT-KERBEROS-5. See the
+\fIXsecurity\fP(__miscmansuffix__) manual page for information on the
+operation of these protocols.
+.PP
+Authorization data required by the above protocols is passed to the
+server in a private file named with the \fB\-auth\fP command line
+option. Each time the server is about to accept the first connection
+after a reset (or when the server is starting), it reads this file.
+If this file contains any authorization records, the local host is not
+automatically allowed access to the server, and only clients which
+send one of the authorization records contained in the file in the
+connection setup information will be allowed access. See the
+\fIXau\fP manual page for a description of the binary format of this
+file. See \fIxauth\fP(1) for maintenance of this file, and distribution
+of its contents to remote hosts.
+.PP
+The X server also uses a host-based access control list for deciding
+whether or not to accept connections from clients on a particular machine.
+If no other authorization mechanism is being used,
+this list initially consists of the host on which the server is running as
+well as any machines listed in the file \fI/etc/X\fBn\fI.hosts\fR, where
+\fBn\fP is the display number of the server. Each line of the file should
+contain either an Internet hostname (e.g. expo.lcs.mit.edu) or a complete
+name in the format \fIfamily\fP:\fIname\fP as described in the
+\fIxhost\fP(1) manual page.
+There should be no leading or trailing spaces on any lines. For example:
+.sp
+.in +8
+.nf
+joesworkstation
+corporate.company.com
+star::
+inet:bigcpu
+local:
+.fi
+.in -8
+.PP
+Users can add or remove hosts from this list and enable or disable access
+control using the \fIxhost\fP command from the same machine as the server.
+.PP
+If the X FireWall Proxy (\fIxfwp\fP) is being used without a sitepolicy,
+host-based authorization must be turned on for clients to be able to
+connect to the X server via the \fIxfwp\fP. If \fIxfwp\fP is run without
+a configuration file and thus no sitepolicy is defined, if \fIxfwp\fP
+is using an X server where xhost + has been run to turn off host-based
+authorization checks, when a client tries to connect to this X server
+via \fIxfwp\fP, the X server will deny the connection. See \fIxfwp\fP(1)
+for more information about this proxy.
+.PP
+The X protocol intrinsically does not have any notion of window operation
+permissions or place any restrictions on what a client can do; if a program can
+connect to a display, it has full run of the screen.
+X servers that support the SECURITY extension fare better because clients
+can be designated untrusted via the authorization they use to connect; see
+the \fIxauth\fP(1) manual page for details. Restrictions are imposed
+on untrusted clients that curtail the mischief they can do. See the SECURITY
+extension specification for a complete list of these restrictions.
+.PP
+Sites that have better
+authentication and authorization systems might wish to make
+use of the hooks in the libraries and the server to provide additional
+security models.
+.SH SIGNALS
+The X server attaches special meaning to the following signals:
+.TP 8
+.I SIGHUP
+This signal causes the server to close all existing connections, free all
+resources, and restore all defaults. It is sent by the display manager
+whenever the main user's main application (usually an \fIxterm\fP or window
+manager) exits to force the server to clean up and prepare for the next
+user.
+.TP 8
+.I SIGTERM
+This signal causes the server to exit cleanly.
+.TP 8
+.I SIGUSR1
+This signal is used quite differently from either of the above. When the
+server starts, it checks to see if it has inherited SIGUSR1 as SIG_IGN
+instead of the usual SIG_DFL. In this case, the server sends a SIGUSR1 to
+its parent process after it has set up the various connection schemes.
+\fIXdm\fP uses this feature to recognize when connecting to the server
+is possible.
+.SH FONTS
+The X server
+can obtain fonts from directories and/or from font servers.
+The list of directories and font servers
+the X server uses when trying to open a font is controlled
+by the \fIfont path\fP.
+.LP
+The default font path is
+__default_font_path__ .
+.LP
+The font path can be set with the \fB\-fp\fP option or by \fIxset\fP(1)
+after the server has started.
+.SH FILES
+.TP 30
+.I /etc/X\fBn\fP.hosts
+Initial access control list for display number \fBn\fP
+.TP 30
+.IR /usr/share/fonts/X11/misc,
+ /usr/share/fonts/X11/75dpi,
+ /usr/share/fonts/X11/100dpi
+Bitmap font directories
+.TP 30
+.IR /usr/share/fonts/X11/Type1
+Outline font directories
+.TP 30
+.I /usr/share/nx/rgb
+Color database
+.TP 30
+.I /tmp/.X11-unix/X\fBn\fP
+Unix domain socket for display number \fBn\fP
+.TP 30
+.IR /tmp/rcX\fBn\fP
+Kerberos 5 replay cache for display number \fBn\fP
+.SH "SEE ALSO"
+Protocols:
+.I "X Window System Protocol,"
+.I "NX Compression Protocol,"
+.I "The X Font Service Protocol,"
+.I "X Display Manager Control Protocol"
+.PP
+Fonts: \fIbdftopcf\fP(1), \fImkfontdir\fP(1), \fImkfontscale\fP(1),
+\fIxfs\fP(1), \fIxlsfonts\fP(1), \fIxfontsel\fP(1), \fIxfd\fP(1),
+.I "X Logical Font Description Conventions"
+.PP
+Security: \fIXsecurity\fP(__miscmansuffix__), \fIxauth\fP(1), \fIXau\fP(1),
+\fIxdm\fP(1), \fIxhost\fP(1), \fIxfwp\fP(1),
+.I "Security Extension Specification"
+.PP
+Starting the server: \fIxdm\fP(1), \fIxinit\fP(1)
+.PP
+Controlling the server once started: \fIxset\fP(1), \fIxsetroot\fP(1),
+\fIxhost\fP(1)
+.PP
+Server-specific man pages:
+\fIXdec\fP(1), \fIXmacII\fP(1), \fIXsun\fP(1), \fIXnest\fP(1),
+\fIXvfb\fP(1), \fIXFree86\fP(1), \fIXDarwin\fP(1).
+.PP
+Server internal documentation:
+.I "Definition of the Porting Layer for the X v11 Sample Server"
+.SH AUTHORS
+The first sample X server was originally written by Susan Angebranndt,
+Raymond Drewry, Philip Karlton, and Todd Newman, from Digital Equipment
+Corporation, with support from a large cast. It has since been
+extensively rewritten by Keith Packard and Bob Scheifler, from MIT. Dave
+Wiggins took over post-R5 and made substantial improvements.
+.PP
+The first implementation of nx-X11 (version 1.x up to 3.5.x) was written
+by NoMachine (maintained until 2011).
+.PP
+The current implementation of nx-X11 is maintained by various projects,
+amongst others The Arctica Project, TheQVD (Qindel Group) and X2Go.
+.PP
+This manual page was written by Per Hansen <spamhans@yahoo.de>, and
+modified by Marcelo Boveto Shima <marceloshima@gmail.com> and Mike
+Gabriel <mike.gabriel@das-netzwerkteam.de>. In 2016, the original
+Xserver.man page shipped with nx-X11 was merged into the \fBnxagent\fR
+man page and received a major update by Mike Gabriel
+<mike.gabriel@das-netzwerkteam.de>.
+
diff --git a/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm b/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm
new file mode 100644
index 000000000..bcdaa2204
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/nxagent.xpm
@@ -0,0 +1,49 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+/* XPM */
+static char *nxagentIconData[] = {
+"16 16 5 1",
+" c None",
+"! c black",
+"# c #FF0000",
+"$ c #424242",
+"% c #750202",
+" ",
+"############### ",
+"# #$",
+"# #% #######% #$",
+"# #% #%%#%%#% #$",
+"# #% #% #% #% #$",
+"# #% #% #% #% #$",
+"# #% #% #% #% #$",
+"# %% #% #% #% #$",
+"# #% #% #% #$",
+"# #% #% #% #% #$",
+"# %% %% %% %% #$",
+"# #$",
+"###############$",
+" $$$$$$$$$$$$$$$",
+" "};
diff --git a/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm b/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm
new file mode 100644
index 000000000..3fb4362d1
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/nxmissing.xpm
@@ -0,0 +1,56 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+static char *placeholderXpm[] = {
+/* columns rows colors chars-per-pixel */
+"14 16 10 1",
+" c #000000",
+". c #0000FF",
+"X c #008400",
+"o c #00FF00",
+"O c #00FFFF",
+"+ c #FF0000",
+"@ c #FF00FF",
+"# c #848484",
+"$ c #BDBDBD",
+"% c #FFFFFF",
+/* pixels */
+" #%%%",
+" %%%%%%%%%##%%",
+" %$$$$$$$$#%#%",
+" %$$$XX$$$#%%#",
+" %$$XoX $$ ",
+" %$$XXX $$$$% ",
+" %$$$ $$$$$% ",
+" %$$$$$$... % ",
+" %$+$$$$.O. % ",
+" %$@+$$$... % ",
+" %$@@+$$ $% ",
+" %$@@@+$$$$$% ",
+" %$ +$$$$% ",
+" %$$$$$$$$$$% ",
+" %%%%%%%%%%%% ",
+" "
+};
diff --git a/nx-X11/programs/Xserver/hw/nxagent/screensaver b/nx-X11/programs/Xserver/hw/nxagent/screensaver
new file mode 100644
index 000000000..a9ca85114
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/screensaver
@@ -0,0 +1,711 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
+/* Copyright (c) 2008-2014 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
+/* Copyright (c) 2011-2016 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
+/* Copyright (c) 2014-2016 Mihai Moldovan <ionic@ionic.de> */
+/* Copyright (c) 2014-2016 Ulrich Sibiller <uli42@gmx.de> */
+/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/* NOTE: This software has received contributions from various other */
+/* contributors, only the core maintainers and supporters are listed as */
+/* copyright holders. Please contact us, if you feel you should be listed */
+/* as copyright holder, as well. */
+/* */
+/**************************************************************************/
+
+#define screensaver_width 256
+#define screensaver_height 256
+static unsigned char screensaver_bits[] = {
+ 0xa8, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x40, 0x55,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x55, 0x05, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0xa0,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x15, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0xaa,
+ 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0xaa, 0x0a, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xaa, 0x2a, 0x80, 0x02, 0x80, 0xaa, 0xaa, 0x82, 0x0a, 0xa8, 0x28, 0x80,
+ 0x8a, 0x80, 0x2a, 0x80, 0x80, 0x8a, 0xa2, 0x82, 0x0a, 0xaa, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2a, 0x02, 0x80, 0x82, 0x41, 0x40, 0x00, 0x50,
+ 0x55, 0x41, 0x00, 0x00, 0x04, 0x00, 0x54, 0x40, 0x10, 0x00, 0x40, 0x00,
+ 0x51, 0x55, 0x00, 0x15, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x00, 0x10, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x8a, 0x02, 0x00, 0x02,
+ 0x00, 0x20, 0xa2, 0x00, 0x80, 0x00, 0x08, 0x00, 0xaa, 0x2a, 0x00, 0x2a,
+ 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x80,
+ 0x01, 0x00, 0x01, 0x50, 0x45, 0x05, 0x00, 0x01, 0x10, 0x10, 0x40, 0x11,
+ 0x40, 0x00, 0x44, 0x00, 0x50, 0x15, 0x01, 0x15, 0x04, 0x00, 0x40, 0x00,
+ 0x05, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x50, 0x20, 0x00, 0x00, 0xa2,
+ 0xaa, 0x2a, 0x00, 0x00, 0x02, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0xa2, 0xaa, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x01, 0x40, 0x44, 0x15, 0x10, 0x01,
+ 0x10, 0x10, 0x40, 0x01, 0x40, 0x00, 0x00, 0x00, 0x54, 0x55, 0x41, 0x45,
+ 0x04, 0x00, 0x40, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x54,
+ 0x20, 0x80, 0x00, 0x82, 0xaa, 0x0a, 0x00, 0x00, 0x22, 0x00, 0x80, 0x0a,
+ 0x00, 0x00, 0x82, 0x00, 0xa0, 0x8a, 0x22, 0x02, 0x00, 0x08, 0x20, 0x00,
+ 0xa8, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x2a, 0x10, 0x40, 0x00, 0x01,
+ 0x54, 0x45, 0x10, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00,
+ 0x50, 0x45, 0x05, 0x41, 0x00, 0x04, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x00, 0x28, 0x00, 0xaa, 0xaa, 0x0a, 0x0a, 0x00,
+ 0x20, 0x08, 0x00, 0x20, 0x00, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x22, 0x2a,
+ 0x00, 0x00, 0x0a, 0x00, 0xa8, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0a,
+ 0x50, 0x05, 0x00, 0x01, 0x55, 0x45, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40,
+ 0x01, 0x00, 0x00, 0x00, 0x40, 0x55, 0x11, 0x00, 0x00, 0x54, 0x01, 0x00,
+ 0x44, 0x01, 0x00, 0x00, 0x05, 0x40, 0x00, 0x05, 0x00, 0x08, 0x00, 0x80,
+ 0xaa, 0xaa, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x80, 0x00,
+ 0x80, 0xaa, 0x28, 0x20, 0x00, 0x00, 0x02, 0x00, 0x80, 0x02, 0x00, 0x00,
+ 0x28, 0x00, 0x80, 0x02, 0x10, 0x10, 0x00, 0x01, 0x54, 0x45, 0x01, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x55, 0x14, 0x00,
+ 0x00, 0x04, 0x04, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x40, 0x40, 0x01,
+ 0x08, 0x00, 0x80, 0x00, 0xa8, 0xa2, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0xa0, 0xaa, 0x00, 0x80, 0x28, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00,
+ 0x80, 0x02, 0x00, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x14, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x40, 0x00, 0x00, 0x08, 0x20, 0x80, 0x00, 0x08, 0x08, 0x80, 0x80,
+ 0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x8a, 0x00,
+ 0x02, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01,
+ 0x10, 0x10, 0x00, 0x01, 0x10, 0x45, 0x55, 0x01, 0x00, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x02, 0x00, 0x08, 0x00, 0x00,
+ 0x20, 0xa2, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x80, 0x00, 0x02, 0x04, 0x00, 0x40, 0x00, 0x04, 0x04, 0x40, 0x40,
+ 0x00, 0x01, 0x00, 0x04, 0x04, 0x00, 0x00, 0x01, 0x00, 0x51, 0x45, 0x05,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x45, 0x01,
+ 0x2a, 0x80, 0xaa, 0xaa, 0x82, 0xaa, 0x2a, 0xa0, 0x02, 0x02, 0x80, 0xa8,
+ 0x00, 0x2a, 0xa0, 0x02, 0x80, 0xa2, 0x00, 0xa0, 0xa0, 0x0a, 0xa0, 0x00,
+ 0x00, 0x00, 0x80, 0x88, 0x02, 0x00, 0x08, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x41, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0xaa, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x05, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x15, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa8, 0xaa,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x15, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x2a, 0x20, 0x00, 0x00, 0x41, 0x05, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14,
+ 0x40, 0x10, 0x44, 0x15, 0x15, 0x00, 0x00, 0x50, 0x01, 0x00, 0x50, 0x55,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x10, 0x50, 0x40,
+ 0x82, 0x08, 0x02, 0x08, 0x20, 0x08, 0x00, 0x22, 0xa0, 0x20, 0x88, 0x00,
+ 0x22, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x80, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x88, 0x20, 0x44, 0x10, 0x01, 0x04,
+ 0x50, 0x04, 0x00, 0x41, 0x10, 0x11, 0x44, 0x00, 0x41, 0x00, 0x00, 0x54,
+ 0x41, 0x00, 0x40, 0x55, 0x15, 0x00, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x54, 0x11, 0x04, 0x11, 0x80, 0x20, 0x02, 0x08, 0xa0, 0x08, 0x00, 0x02,
+ 0x88, 0x20, 0x88, 0x00, 0x82, 0x00, 0x00, 0x2a, 0x22, 0x00, 0x80, 0xaa,
+ 0x2a, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x08, 0x20,
+ 0x40, 0x10, 0x01, 0x04, 0x50, 0x04, 0x00, 0x01, 0x04, 0x41, 0x44, 0x00,
+ 0x41, 0x00, 0x00, 0x15, 0x05, 0x14, 0x15, 0x50, 0x10, 0x05, 0x40, 0x41,
+ 0x41, 0x10, 0x45, 0x05, 0x50, 0x04, 0x04, 0x10, 0x80, 0x20, 0x02, 0x08,
+ 0xa0, 0x08, 0x00, 0x02, 0x08, 0x22, 0x82, 0x00, 0x82, 0x00, 0x00, 0x0a,
+ 0x2a, 0x22, 0x8a, 0x22, 0x22, 0x08, 0x80, 0x22, 0x22, 0x88, 0x88, 0x02,
+ 0x28, 0x02, 0x08, 0x20, 0x40, 0x10, 0x15, 0x54, 0x10, 0x05, 0x00, 0x14,
+ 0x04, 0x41, 0x44, 0x05, 0x41, 0x00, 0x00, 0x05, 0x50, 0x01, 0x41, 0x04,
+ 0x05, 0x11, 0x00, 0x05, 0x44, 0x44, 0x50, 0x00, 0x10, 0x05, 0x50, 0x10,
+ 0x80, 0x0a, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x20, 0xa8, 0x82, 0x82, 0x00,
+ 0x2a, 0x00, 0x80, 0x02, 0x22, 0x02, 0x82, 0x20, 0x20, 0x08, 0x20, 0x88,
+ 0x82, 0x88, 0x8a, 0x00, 0x88, 0x0a, 0x80, 0x20, 0x40, 0x04, 0x01, 0x04,
+ 0x10, 0x05, 0x00, 0x40, 0x04, 0x41, 0x41, 0x00, 0x11, 0x00, 0x40, 0x01,
+ 0x41, 0x41, 0x41, 0x14, 0x15, 0x11, 0x40, 0x44, 0x04, 0x44, 0x40, 0x00,
+ 0x44, 0x15, 0x00, 0x11, 0x80, 0x08, 0x02, 0x08, 0x20, 0x0a, 0x00, 0x80,
+ 0x08, 0x82, 0x82, 0x00, 0x22, 0x00, 0xa0, 0x00, 0x22, 0x22, 0x82, 0x20,
+ 0x22, 0x0a, 0x20, 0x28, 0x82, 0x82, 0x88, 0x00, 0x88, 0x2a, 0x00, 0x22,
+ 0x44, 0x10, 0x01, 0x04, 0x10, 0x04, 0x00, 0x41, 0x04, 0x01, 0x41, 0x00,
+ 0x41, 0x00, 0x50, 0x01, 0x14, 0x14, 0x01, 0x55, 0x10, 0x15, 0x40, 0x45,
+ 0x05, 0x01, 0x45, 0x00, 0x04, 0x55, 0x04, 0x11, 0x82, 0x20, 0x02, 0x08,
+ 0x20, 0x08, 0x00, 0x22, 0x08, 0x82, 0x80, 0x00, 0x82, 0x00, 0xa8, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0xaa, 0x88, 0x20, 0x41, 0x10, 0x55, 0x54, 0x11, 0x04, 0x00, 0x14,
+ 0x04, 0x01, 0x41, 0x15, 0x41, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x54, 0x51, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x15, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xa8, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x15, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x14, 0x40, 0x01, 0x41, 0x40, 0x01, 0x14, 0x10, 0x01, 0x00, 0x40,
+ 0x01, 0x04, 0x14, 0x14, 0x14, 0x10, 0x04, 0x00, 0xa0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x82, 0xa0, 0x20, 0x82,
+ 0xa2, 0x20, 0x02, 0x22, 0x28, 0x02, 0x00, 0x08, 0x8a, 0x22, 0x08, 0x08,
+ 0x22, 0x28, 0x0a, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x44, 0x54,
+ 0x01, 0x00, 0x00, 0x40, 0x41, 0x40, 0x10, 0x04, 0x11, 0x11, 0x04, 0x41,
+ 0x10, 0x04, 0x00, 0x04, 0x04, 0x40, 0x10, 0x00, 0x41, 0x10, 0x11, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xaa, 0x02, 0x00, 0x00, 0xa0,
+ 0x82, 0x80, 0x08, 0x08, 0x02, 0x08, 0x88, 0x80, 0x08, 0x08, 0x00, 0x08,
+ 0x08, 0x20, 0x20, 0x80, 0x80, 0x20, 0x00, 0x00, 0x10, 0x50, 0x14, 0x14,
+ 0x45, 0x05, 0x40, 0x05, 0x41, 0x14, 0x15, 0x50, 0x41, 0x01, 0x04, 0x00,
+ 0x01, 0x04, 0x50, 0x00, 0x11, 0x04, 0x00, 0x14, 0x00, 0x40, 0x10, 0x44,
+ 0x00, 0x11, 0x00, 0x00, 0xa0, 0x88, 0x22, 0xa2, 0x88, 0x08, 0x00, 0x2a,
+ 0x82, 0x22, 0x22, 0xa8, 0x80, 0x0a, 0x08, 0x00, 0x02, 0xa8, 0x8a, 0xaa,
+ 0x08, 0x08, 0x00, 0xa8, 0x00, 0x2a, 0x20, 0x80, 0xaa, 0x20, 0x00, 0x00,
+ 0x00, 0x05, 0x04, 0x15, 0x55, 0x04, 0x40, 0x04, 0x50, 0x54, 0x01, 0x54,
+ 0x00, 0x54, 0x04, 0x00, 0x01, 0x04, 0x40, 0x00, 0x10, 0x04, 0x00, 0x40,
+ 0x05, 0x41, 0x40, 0x40, 0x00, 0x10, 0x00, 0x00, 0x80, 0x08, 0x02, 0x82,
+ 0x80, 0x08, 0x80, 0x20, 0x02, 0x02, 0x02, 0x2a, 0x00, 0xa0, 0x08, 0x00,
+ 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00, 0x8a, 0x20, 0x20, 0x82,
+ 0x00, 0x20, 0x00, 0x00, 0x10, 0x45, 0x04, 0x11, 0x51, 0x04, 0x50, 0x44,
+ 0x44, 0x44, 0x01, 0x15, 0x00, 0x40, 0x05, 0x00, 0x01, 0x04, 0x40, 0x00,
+ 0x10, 0x04, 0x00, 0x00, 0x54, 0x40, 0x40, 0x41, 0x00, 0x10, 0x00, 0x00,
+ 0xa0, 0x28, 0x02, 0x0a, 0x8a, 0x08, 0x20, 0x0a, 0x0a, 0x28, 0x02, 0x0a,
+ 0x00, 0x80, 0x08, 0x00, 0x02, 0x08, 0x80, 0x00, 0x08, 0x08, 0x00, 0x00,
+ 0x88, 0x20, 0x80, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x05, 0x40, 0x00, 0x11, 0x00,
+ 0x01, 0x10, 0x10, 0x01, 0x11, 0x04, 0x00, 0x04, 0x50, 0x40, 0x41, 0x01,
+ 0x01, 0x11, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
+ 0xaa, 0x00, 0x80, 0x02, 0x80, 0x80, 0x20, 0x02, 0x02, 0x20, 0x08, 0x82,
+ 0x08, 0x08, 0x00, 0x08, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x00, 0x00,
+ 0x00, 0x40, 0x01, 0x10, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x40, 0x01,
+ 0x40, 0x14, 0x40, 0x41, 0x05, 0x40, 0x01, 0x14, 0x14, 0x14, 0x00, 0x44,
+ 0x01, 0x45, 0x00, 0x00, 0x14, 0x54, 0x00, 0x00, 0x00, 0x80, 0x02, 0x08,
+ 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x50,
+ 0x55, 0x05, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0xa8, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01,
+ 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0xaa, 0x0a, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x15, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x8a, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x05, 0x50, 0x00, 0x50, 0x40, 0x45, 0x11, 0x00, 0x50,
+ 0x40, 0x41, 0x01, 0x00, 0x14, 0x00, 0x51, 0x40, 0x40, 0x00, 0x05, 0x14,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a,
+ 0x88, 0x02, 0xaa, 0xa8, 0x80, 0x00, 0x00, 0xaa, 0xa8, 0xa2, 0x02, 0x00,
+ 0xa2, 0xa0, 0x22, 0xa8, 0xa0, 0xa0, 0x8a, 0x2a, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x04, 0x01, 0x45, 0x51,
+ 0x04, 0x40, 0x00, 0x45, 0x41, 0x51, 0x01, 0x00, 0x41, 0x50, 0x54, 0x50,
+ 0x50, 0x50, 0x14, 0x14, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x82, 0xa2, 0xa0, 0x02, 0xa0, 0x88, 0x82,
+ 0xa0, 0x88, 0x02, 0x80, 0x82, 0x28, 0x28, 0xa0, 0x20, 0x28, 0x08, 0x8a,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x45, 0x54, 0x00,
+ 0x14, 0x40, 0x41, 0x50, 0x05, 0x51, 0x10, 0x41, 0x41, 0x41, 0x01, 0x00,
+ 0x05, 0x14, 0x10, 0x50, 0x40, 0x10, 0x14, 0x54, 0x04, 0x00, 0x41, 0x55,
+ 0x04, 0x45, 0x01, 0x04, 0x20, 0x02, 0x08, 0x00, 0x2a, 0xa0, 0x00, 0xa0,
+ 0x8a, 0x20, 0xa8, 0xa2, 0xa0, 0xa0, 0x00, 0x80, 0x0a, 0x28, 0x28, 0xa0,
+ 0x20, 0x28, 0x0a, 0x2a, 0x00, 0x00, 0x22, 0x0a, 0x80, 0x88, 0x02, 0x88,
+ 0x04, 0x50, 0x01, 0x00, 0x54, 0x40, 0x01, 0x50, 0x15, 0x10, 0x14, 0x51,
+ 0x40, 0x41, 0x01, 0x00, 0x15, 0x14, 0x14, 0x40, 0x11, 0x14, 0x05, 0x14,
+ 0x00, 0x40, 0x10, 0x00, 0x15, 0x45, 0x04, 0x01, 0x00, 0x00, 0x08, 0x00,
+ 0xa8, 0xa0, 0x00, 0x28, 0x8a, 0x08, 0x0a, 0x28, 0xa0, 0xa0, 0x00, 0x00,
+ 0x2a, 0x0a, 0x28, 0xa0, 0x08, 0x8a, 0x02, 0x0a, 0x00, 0x80, 0x00, 0x08,
+ 0x80, 0x00, 0x00, 0x82, 0x44, 0x11, 0x00, 0x00, 0x50, 0x50, 0x00, 0x10,
+ 0x05, 0x40, 0x15, 0x05, 0x50, 0x50, 0x00, 0x00, 0x14, 0x14, 0x14, 0x40,
+ 0x11, 0x54, 0x00, 0x05, 0x00, 0x00, 0x11, 0x00, 0x01, 0x40, 0x04, 0x44,
+ 0x80, 0x20, 0x0a, 0x00, 0xa0, 0xa0, 0x00, 0x88, 0x82, 0xa8, 0x0a, 0x00,
+ 0xa0, 0xa0, 0x00, 0x00, 0x28, 0x0a, 0x0a, 0xa0, 0x08, 0x0a, 0x00, 0x0a,
+ 0x00, 0x00, 0x22, 0x0a, 0xa2, 0x00, 0x00, 0x88, 0x01, 0x40, 0x15, 0x00,
+ 0x50, 0x51, 0x40, 0x00, 0x01, 0x51, 0x15, 0x00, 0x50, 0x50, 0x00, 0x00,
+ 0x54, 0x14, 0x54, 0x40, 0x05, 0x14, 0x00, 0x05, 0x00, 0x40, 0x41, 0x15,
+ 0x14, 0x45, 0x04, 0x05, 0x00, 0x00, 0x00, 0x80, 0xa0, 0xa0, 0x20, 0x88,
+ 0x80, 0xaa, 0x08, 0x82, 0x28, 0x28, 0x02, 0x20, 0x28, 0x0a, 0x2a, 0xa0,
+ 0x02, 0x0a, 0x88, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x41, 0x40, 0x11, 0x44, 0x00, 0x55, 0x14, 0x44,
+ 0x50, 0x50, 0x01, 0x40, 0x10, 0x54, 0x15, 0x40, 0x01, 0x14, 0x04, 0x45,
+ 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x22, 0xa0, 0x0a, 0x00, 0x00, 0x0a, 0x2a, 0x20, 0x28, 0xa8, 0x00, 0xa0,
+ 0x08, 0xa8, 0x08, 0xa0, 0x00, 0xa8, 0x82, 0x82, 0x02, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x05, 0x00,
+ 0x00, 0x54, 0x55, 0x10, 0x50, 0x50, 0x00, 0x00, 0x05, 0x50, 0x04, 0x40,
+ 0x00, 0x50, 0x40, 0x05, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x80, 0xaa, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a,
+ 0x00, 0x80, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x55, 0x55,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x01,
+ 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xa8, 0xaa,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x82, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x50, 0x55,
+ 0x05, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x28,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0a, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
+ 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x80, 0xaa,
+ 0x2a, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x55, 0x50, 0x15,
+ 0x55, 0x11, 0x55, 0x00, 0x15, 0x00, 0x54, 0x01, 0x00, 0x54, 0x01, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x00, 0x20, 0x82, 0x20, 0x08, 0x82, 0x00, 0x22, 0x80,
+ 0x08, 0x08, 0x28, 0xa2, 0x28, 0x20, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xa2,
+ 0x00, 0x04, 0x41, 0x10, 0x04, 0x11, 0x00, 0x40, 0x10, 0x14, 0x10, 0x54,
+ 0x54, 0x11, 0x10, 0x00, 0x01, 0x00, 0x50, 0x14, 0x15, 0x05, 0x45, 0x01,
+ 0x50, 0x50, 0x44, 0x14, 0x05, 0x00, 0x04, 0x40, 0x20, 0x02, 0x22, 0x02,
+ 0x22, 0x08, 0x20, 0x20, 0x00, 0x08, 0x20, 0xa8, 0x28, 0x22, 0x08, 0x80,
+ 0x02, 0x00, 0x88, 0x22, 0xa2, 0x88, 0x28, 0x02, 0x88, 0x80, 0x22, 0xa2,
+ 0x08, 0x00, 0x08, 0x22, 0x00, 0x04, 0x41, 0x00, 0x04, 0x00, 0x01, 0x40,
+ 0x00, 0x10, 0x40, 0x04, 0x11, 0x10, 0x04, 0x10, 0x05, 0x00, 0x10, 0x04,
+ 0x01, 0x55, 0x45, 0x04, 0x10, 0x50, 0x44, 0x15, 0x01, 0x00, 0x14, 0x10,
+ 0x00, 0x2a, 0xa0, 0x02, 0x2a, 0x20, 0x22, 0x80, 0x02, 0x22, 0x20, 0x02,
+ 0x0a, 0xa0, 0x02, 0x08, 0x0a, 0x00, 0x20, 0x02, 0x82, 0x80, 0x20, 0x02,
+ 0x80, 0x88, 0x28, 0x82, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x44, 0x40, 0x01,
+ 0x14, 0x00, 0x04, 0x00, 0x05, 0x10, 0x40, 0x00, 0x11, 0x10, 0x05, 0x04,
+ 0x14, 0x00, 0x44, 0x44, 0x01, 0x51, 0x44, 0x04, 0x10, 0x45, 0x14, 0x11,
+ 0x01, 0x00, 0x50, 0x11, 0x00, 0x82, 0x20, 0x02, 0x22, 0x20, 0x28, 0x20,
+ 0x08, 0x2a, 0x80, 0x02, 0x02, 0x20, 0x08, 0x00, 0x00, 0x00, 0x28, 0x28,
+ 0x02, 0x8a, 0x22, 0x02, 0xa0, 0xa8, 0x08, 0x8a, 0x00, 0x00, 0x80, 0x22,
+ 0x00, 0x04, 0x41, 0x10, 0x04, 0x01, 0x10, 0x00, 0x10, 0x41, 0x40, 0x01,
+ 0x11, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51, 0x20, 0x82, 0x20, 0x00,
+ 0x02, 0x20, 0x28, 0x20, 0x88, 0x20, 0x80, 0x00, 0x82, 0x20, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x22, 0x10, 0x04, 0x45, 0x10, 0x04, 0x01, 0x10, 0x40,
+ 0x04, 0x40, 0x00, 0x00, 0x41, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41,
+ 0x8a, 0x0a, 0xaa, 0x8a, 0xaa, 0xa8, 0x20, 0xa0, 0x82, 0xa2, 0x80, 0x80,
+ 0xaa, 0xa8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0xa2, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x10, 0x50,
+ 0x41, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x15, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xa0, 0x80, 0x02, 0xa8, 0x28,
+ 0x0a, 0xa0, 0x02, 0xa8, 0x00, 0x8a, 0x02, 0x28, 0x00, 0x00, 0x00, 0x0a,
+ 0x28, 0x80, 0x2a, 0x80, 0x22, 0x80, 0x0a, 0x00, 0xa8, 0x00, 0x28, 0x2a,
+ 0x00, 0x05, 0x00, 0x50, 0x00, 0x00, 0x55, 0x51, 0x14, 0x14, 0x54, 0x54,
+ 0x01, 0x54, 0x01, 0x50, 0x50, 0x05, 0x00, 0x05, 0x00, 0x50, 0x55, 0x40,
+ 0x51, 0x50, 0x15, 0x00, 0x54, 0x05, 0x14, 0x55, 0x00, 0x0a, 0x00, 0xa0,
+ 0x00, 0x80, 0xaa, 0x2a, 0x2a, 0x08, 0x2a, 0xa8, 0x02, 0xaa, 0x02, 0xa0,
+ 0xa0, 0x02, 0x00, 0x0a, 0x00, 0xa8, 0xaa, 0x80, 0x2a, 0xa8, 0x2a, 0x80,
+ 0xaa, 0x0a, 0xa8, 0xaa, 0x01, 0x05, 0x00, 0x50, 0x05, 0x40, 0x55, 0x55,
+ 0x14, 0x00, 0x14, 0x50, 0x05, 0x54, 0x01, 0x40, 0x51, 0x01, 0x00, 0x55,
+ 0x00, 0x54, 0x55, 0x41, 0x15, 0x54, 0x55, 0x40, 0x55, 0x15, 0x54, 0x55,
+ 0x02, 0x0a, 0x00, 0xa0, 0x0a, 0xa0, 0x02, 0x2a, 0x2a, 0x00, 0x0a, 0x88,
+ 0x0a, 0x2a, 0x00, 0x80, 0xaa, 0x00, 0x00, 0xaa, 0x00, 0xaa, 0xa0, 0xa2,
+ 0x0a, 0x2a, 0xa8, 0xa0, 0x0a, 0x0a, 0xaa, 0xa0, 0x01, 0x14, 0x01, 0x40,
+ 0x55, 0x50, 0x01, 0x14, 0x14, 0x00, 0x05, 0x04, 0x15, 0x15, 0x00, 0x00,
+ 0x51, 0x00, 0x00, 0x54, 0x05, 0x14, 0x40, 0x45, 0x05, 0x15, 0x50, 0x41,
+ 0x01, 0x14, 0x54, 0x40, 0x02, 0xa8, 0x00, 0x80, 0xaa, 0xa8, 0x00, 0x2a,
+ 0x28, 0x88, 0x02, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8,
+ 0x0a, 0x0a, 0xa0, 0xa2, 0x82, 0x0a, 0xa0, 0xa0, 0x00, 0x28, 0x2a, 0xa0,
+ 0x01, 0x50, 0x00, 0x00, 0x55, 0x50, 0x00, 0x14, 0x54, 0x54, 0x05, 0x15,
+ 0x14, 0x15, 0x00, 0x00, 0x11, 0x00, 0x00, 0x50, 0x05, 0x15, 0x00, 0x40,
+ 0x01, 0x05, 0x40, 0x51, 0x00, 0x14, 0x14, 0x40, 0x00, 0xa8, 0x00, 0x00,
+ 0xa8, 0x28, 0x00, 0x28, 0x28, 0xa8, 0x02, 0x80, 0x0a, 0x0a, 0x00, 0x80,
+ 0x08, 0x00, 0x00, 0x80, 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0xaa, 0xaa, 0xa8,
+ 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x44, 0x01, 0x00, 0x50, 0x55, 0x00, 0x14,
+ 0x50, 0x14, 0x01, 0x00, 0x15, 0x05, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00,
+ 0x15, 0x05, 0x00, 0x50, 0x41, 0x55, 0x55, 0x51, 0x55, 0x15, 0x15, 0x40,
+ 0x00, 0x80, 0x02, 0x00, 0xa0, 0x28, 0x00, 0x0a, 0x28, 0x0a, 0x02, 0x00,
+ 0x8a, 0x0a, 0x00, 0xa0, 0x2a, 0x00, 0x00, 0x00, 0x8a, 0x0a, 0x00, 0xa0,
+ 0x80, 0xaa, 0xaa, 0xa8, 0xaa, 0x2a, 0x0a, 0xa0, 0x01, 0x40, 0x01, 0x00,
+ 0x50, 0x55, 0x00, 0x14, 0x50, 0x05, 0x00, 0x00, 0x14, 0x05, 0x00, 0x50,
+ 0x50, 0x00, 0x00, 0x00, 0x15, 0x05, 0x00, 0x50, 0x40, 0x55, 0x55, 0x51,
+ 0x55, 0x15, 0x05, 0x50, 0x00, 0x80, 0x02, 0x2a, 0xa8, 0x28, 0x00, 0x0a,
+ 0xa8, 0x0a, 0x80, 0xaa, 0x82, 0x02, 0x00, 0x20, 0xa0, 0x00, 0xa0, 0x82,
+ 0x8a, 0x0a, 0x00, 0xa0, 0x80, 0x02, 0x00, 0x28, 0x00, 0x00, 0x0a, 0xa0,
+ 0x00, 0x00, 0x05, 0x14, 0x50, 0x54, 0x00, 0x15, 0x50, 0x05, 0x40, 0x55,
+ 0x01, 0x05, 0x00, 0x10, 0x40, 0x01, 0x40, 0x01, 0x05, 0x15, 0x50, 0x51,
+ 0x40, 0x01, 0x00, 0x50, 0x00, 0x00, 0x05, 0x50, 0x00, 0x00, 0x0a, 0x2a,
+ 0xa8, 0xa8, 0x80, 0x0a, 0xa0, 0x02, 0x80, 0x0a, 0x80, 0x02, 0x00, 0x08,
+ 0x80, 0x02, 0xa0, 0x82, 0x0a, 0x2a, 0xa8, 0xa0, 0x80, 0x02, 0x2a, 0xa8,
+ 0x80, 0x8a, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x54, 0x55, 0x50, 0x55, 0x05,
+ 0x50, 0x01, 0x00, 0x00, 0x44, 0x05, 0x00, 0x04, 0x00, 0x05, 0x40, 0x55,
+ 0x05, 0x54, 0x55, 0x50, 0x00, 0x55, 0x15, 0x50, 0x55, 0x05, 0x05, 0x50,
+ 0x00, 0x00, 0x00, 0xa8, 0x2a, 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x08, 0x00,
+ 0x8a, 0x02, 0x00, 0x0a, 0x00, 0x00, 0x80, 0xaa, 0x02, 0xaa, 0x2a, 0x28,
+ 0x80, 0xaa, 0x0a, 0xa0, 0xaa, 0x82, 0x02, 0x28, 0x00, 0x00, 0x00, 0x50,
+ 0x15, 0x40, 0x55, 0x05, 0x40, 0x01, 0x10, 0x00, 0x55, 0x01, 0x00, 0x05,
+ 0x00, 0x00, 0x00, 0x55, 0x01, 0x54, 0x15, 0x50, 0x00, 0x55, 0x05, 0x40,
+ 0x55, 0x01, 0x05, 0x50, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x80, 0x0a, 0x0a,
+ 0xa0, 0x00, 0x00, 0xa0, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x2a,
+ 0x00, 0xa0, 0x0a, 0x28, 0x00, 0xa8, 0x00, 0x80, 0x2a, 0x80, 0x02, 0x28,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x55, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0xa0, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x50, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa,
+ 0xaa, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x50, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x55, 0x05, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x0a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x45, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x22, 0xa0, 0x22, 0xa8, 0x0a, 0xa8, 0x00,
+ 0xa8, 0xa0, 0x28, 0x80, 0xaa, 0x22, 0x28, 0xa0, 0x02, 0x2a, 0x2a, 0xa0,
+ 0x02, 0x8a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x15, 0x50, 0x15, 0x54, 0x15, 0x54, 0x01, 0x55, 0x41, 0x55, 0x00,
+ 0x55, 0x11, 0x54, 0x50, 0x05, 0x54, 0x54, 0x54, 0x05, 0x54, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x08, 0x08,
+ 0x20, 0x08, 0x02, 0x82, 0x82, 0x82, 0x82, 0x00, 0xaa, 0x08, 0x20, 0x20,
+ 0x08, 0x08, 0x08, 0x0a, 0x0a, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x10, 0x04, 0x10, 0x10, 0x00, 0x01, 0x04,
+ 0x01, 0x01, 0x01, 0x01, 0x54, 0x14, 0x11, 0x00, 0x10, 0x10, 0x04, 0x04,
+ 0x04, 0x10, 0x00, 0x14, 0x51, 0x10, 0x44, 0x01, 0x50, 0x44, 0x44, 0x14,
+ 0xa0, 0x00, 0x02, 0x08, 0x08, 0x80, 0x00, 0x82, 0x00, 0x82, 0x80, 0x00,
+ 0xa8, 0x28, 0x00, 0xa0, 0x0a, 0x20, 0x08, 0x02, 0x08, 0x08, 0x00, 0x00,
+ 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x05, 0x04, 0x00,
+ 0x10, 0x00, 0x55, 0x45, 0x55, 0x41, 0x40, 0x00, 0x54, 0x54, 0x00, 0x50,
+ 0x05, 0x10, 0x04, 0x55, 0x05, 0x04, 0x00, 0x44, 0x10, 0x14, 0x45, 0x04,
+ 0x10, 0x54, 0x54, 0x04, 0x00, 0x0a, 0x02, 0x00, 0x08, 0x80, 0xaa, 0x82,
+ 0xaa, 0x82, 0x80, 0x00, 0x2a, 0xaa, 0x00, 0x08, 0x08, 0x20, 0x02, 0xaa,
+ 0x0a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00,
+ 0x10, 0x14, 0x04, 0x00, 0x04, 0x00, 0x01, 0x40, 0x00, 0x40, 0x40, 0x00,
+ 0x15, 0x45, 0x15, 0x04, 0x04, 0x10, 0x01, 0x01, 0x00, 0x04, 0x00, 0x05,
+ 0x15, 0x10, 0x44, 0x04, 0x14, 0x14, 0x41, 0x04, 0x08, 0x08, 0x0a, 0x08,
+ 0x08, 0x80, 0x02, 0x82, 0x80, 0x20, 0x20, 0x80, 0x8a, 0x8a, 0x22, 0x02,
+ 0x02, 0xa0, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x05, 0x54, 0x15, 0x55, 0x01, 0x55, 0x01,
+ 0x55, 0x51, 0x51, 0x01, 0x45, 0x05, 0x00, 0x54, 0x15, 0x40, 0x00, 0x54,
+ 0x45, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0x02, 0xa8, 0x82, 0xaa, 0x00, 0xaa, 0x00, 0x2a, 0xa8, 0xa8, 0x80,
+ 0x82, 0x22, 0x20, 0xa8, 0x0a, 0x20, 0x00, 0xa8, 0x80, 0xaa, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x55, 0x55, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xa0, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00, 0xa8, 0xaa, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+ 0x2a, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x00, 0x54, 0x55, 0x01, 0x00, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a,
+ 0x00, 0xa8, 0xaa, 0x02, 0x00, 0x80, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x50, 0x55, 0x05,
+ 0x00, 0x00, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x54, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x0a, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x0a, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05,
+ 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x80, 0xaa, 0x2a,
+ 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa8, 0x02, 0x08, 0x00, 0x10, 0x50, 0x50, 0x50, 0x40, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x50, 0x00,
+ 0x50, 0x00, 0x05, 0x04, 0x01, 0x05, 0x50, 0x40, 0x54, 0x05, 0x04, 0x05,
+ 0x8a, 0x20, 0x20, 0x88, 0xa0, 0x28, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00,
+ 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x20, 0x00, 0x82, 0x82, 0x08, 0x8a,
+ 0x82, 0x08, 0x88, 0xa0, 0xa8, 0x0a, 0x22, 0x28, 0x00, 0x41, 0x00, 0x04,
+ 0x41, 0x44, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x55, 0x55,
+ 0x00, 0x00, 0x10, 0x00, 0x01, 0x41, 0x10, 0x44, 0x44, 0x10, 0x04, 0x41,
+ 0x50, 0x15, 0x11, 0x10, 0x80, 0x80, 0x00, 0x02, 0x82, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x80, 0x00,
+ 0x02, 0x22, 0x20, 0x08, 0x20, 0x20, 0x02, 0x22, 0xa0, 0x2a, 0x22, 0x20,
+ 0x00, 0x41, 0x10, 0x01, 0x44, 0x00, 0x00, 0x40, 0x41, 0x51, 0x04, 0x14,
+ 0x15, 0x00, 0x11, 0x44, 0x50, 0x54, 0x40, 0x01, 0x05, 0x10, 0x00, 0x04,
+ 0x10, 0x40, 0x01, 0x44, 0x10, 0x15, 0x51, 0x00, 0xa8, 0x80, 0x00, 0xaa,
+ 0x82, 0x00, 0x00, 0x20, 0x22, 0x8a, 0xa2, 0x22, 0x22, 0x80, 0xa0, 0x88,
+ 0x88, 0x88, 0x88, 0x02, 0x2a, 0x20, 0x00, 0x08, 0xa0, 0x2a, 0xaa, 0x22,
+ 0x20, 0x8a, 0xa0, 0x02, 0x04, 0x01, 0x01, 0x01, 0x40, 0x00, 0x00, 0x40,
+ 0x10, 0x10, 0x41, 0x54, 0x11, 0x00, 0x11, 0x40, 0x54, 0x05, 0x04, 0x05,
+ 0x50, 0x11, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40, 0x10, 0x45, 0x00, 0x15,
+ 0x82, 0x80, 0x08, 0x02, 0x80, 0x00, 0x00, 0x00, 0x22, 0x88, 0x02, 0x02,
+ 0x22, 0x00, 0x82, 0x08, 0x02, 0x08, 0x02, 0x0a, 0x80, 0x22, 0x00, 0x08,
+ 0x20, 0x00, 0x02, 0x20, 0x20, 0xa2, 0x00, 0x28, 0x01, 0x01, 0x05, 0x01,
+ 0x40, 0x00, 0x00, 0x40, 0x14, 0x51, 0x41, 0x44, 0x11, 0x40, 0x04, 0x11,
+ 0x04, 0x05, 0x01, 0x14, 0x00, 0x15, 0x00, 0x04, 0x10, 0x00, 0x01, 0x40,
+ 0x10, 0x51, 0x01, 0x50, 0x82, 0x00, 0x02, 0x02, 0x80, 0x00, 0x00, 0x80,
+ 0xa2, 0x88, 0x2a, 0x28, 0x22, 0x80, 0x02, 0x28, 0x8a, 0x88, 0x00, 0x28,
+ 0x00, 0x22, 0x00, 0x08, 0x20, 0x00, 0x02, 0x20, 0xa0, 0xa8, 0x02, 0x20,
+ 0x01, 0x05, 0x05, 0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x40, 0x55, 0x15, 0x00, 0x00, 0x00, 0x01, 0x44, 0x00, 0x04,
+ 0x40, 0x40, 0x04, 0x44, 0x10, 0x51, 0x15, 0x40, 0x82, 0x00, 0x02, 0x08,
+ 0x82, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa,
+ 0x2a, 0x00, 0x00, 0x00, 0x02, 0x82, 0x08, 0x08, 0x80, 0x20, 0x08, 0x22,
+ 0xa0, 0xa0, 0x2a, 0x20, 0x14, 0x01, 0x00, 0x50, 0x50, 0x01, 0x00, 0x00,
+ 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00,
+ 0x51, 0x00, 0x05, 0x15, 0x00, 0x05, 0x50, 0x50, 0x50, 0x40, 0x15, 0x05,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x80, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x2a, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x54, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xa0, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x50, 0x55, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00,
+ 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x2a, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xaa, 0x15, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00,
+ 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55,
+ 0xa2, 0x00, 0x80, 0x02, 0x0a, 0xa2, 0x82, 0x02, 0x0a, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0a, 0xa8, 0xa0, 0x80, 0x82, 0xa0, 0x11, 0x01, 0x00, 0x04,
+ 0x11, 0x50, 0x41, 0x04, 0x11, 0x10, 0x00, 0x14, 0x44, 0x40, 0x00, 0x41,
+ 0x11, 0x00, 0x14, 0x00, 0x44, 0x05, 0x05, 0x04, 0x45, 0x00, 0x10, 0x44,
+ 0x11, 0x11, 0x04, 0x44, 0xa2, 0x02, 0x20, 0x80, 0x20, 0x28, 0x20, 0x08,
+ 0x02, 0x20, 0x80, 0x22, 0xa8, 0xa8, 0xa0, 0x82, 0x28, 0x00, 0x28, 0x80,
+ 0x22, 0x08, 0x82, 0x0a, 0x22, 0x80, 0x00, 0x82, 0x20, 0x00, 0x88, 0x8a,
+ 0x51, 0x05, 0x50, 0x00, 0x10, 0x11, 0x11, 0x10, 0x01, 0x50, 0x40, 0x10,
+ 0x54, 0x04, 0x11, 0x04, 0x41, 0x00, 0x50, 0x40, 0x10, 0x04, 0x44, 0x10,
+ 0x44, 0x40, 0x01, 0x01, 0x10, 0x10, 0x44, 0x14, 0xa2, 0x00, 0xa0, 0x00,
+ 0xa8, 0x02, 0xa0, 0x0a, 0x02, 0xa0, 0xa0, 0x00, 0x0a, 0x82, 0x08, 0x82,
+ 0x20, 0x00, 0xa0, 0x20, 0x20, 0x08, 0x22, 0x08, 0x02, 0x80, 0x02, 0x02,
+ 0x20, 0xa8, 0x8a, 0x82, 0x51, 0x01, 0x40, 0x01, 0x55, 0x01, 0x10, 0x00,
+ 0x01, 0x40, 0x41, 0x00, 0x04, 0x54, 0x50, 0x41, 0x40, 0x00, 0x40, 0x10,
+ 0x10, 0x04, 0x41, 0x05, 0x01, 0x00, 0x05, 0x01, 0x10, 0x10, 0x40, 0x50,
+ 0xa2, 0x08, 0x80, 0x82, 0xa0, 0x8a, 0x20, 0x00, 0x02, 0x80, 0x22, 0x00,
+ 0x02, 0x0a, 0x28, 0x80, 0x20, 0x00, 0x80, 0x20, 0x08, 0x88, 0xa0, 0x00,
+ 0x02, 0x00, 0x0a, 0x02, 0x20, 0x08, 0x80, 0xa0, 0x51, 0x01, 0x00, 0x44,
+ 0x50, 0x11, 0x10, 0x00, 0x01, 0x00, 0x11, 0x00, 0x01, 0x01, 0x04, 0x40,
+ 0x10, 0x00, 0x40, 0x11, 0x10, 0x10, 0x11, 0x00, 0x01, 0x00, 0x10, 0x01,
+ 0x10, 0x10, 0x40, 0x50, 0xa2, 0x08, 0x00, 0x88, 0x80, 0x08, 0x20, 0x00,
+ 0x02, 0x02, 0x22, 0x00, 0x02, 0x02, 0x08, 0x20, 0x20, 0x00, 0x80, 0x08,
+ 0x08, 0x88, 0x20, 0x80, 0x00, 0x00, 0x20, 0x02, 0x20, 0x28, 0x80, 0xa0,
+ 0x51, 0x11, 0x10, 0x44, 0x40, 0x50, 0x40, 0x10, 0x01, 0x00, 0x11, 0x00,
+ 0x01, 0x01, 0x04, 0x40, 0x10, 0x00, 0x01, 0x11, 0x04, 0x50, 0x10, 0x00,
+ 0x01, 0x40, 0x10, 0x04, 0x11, 0x50, 0x00, 0x01, 0xa2, 0x28, 0x20, 0x82,
+ 0x0a, 0x20, 0xa0, 0x0a, 0x02, 0x02, 0x22, 0x88, 0x00, 0x82, 0x08, 0x22,
+ 0x08, 0x80, 0x80, 0x28, 0x08, 0x28, 0x20, 0x88, 0x00, 0x80, 0x08, 0xaa,
+ 0x20, 0xa0, 0x82, 0xaa, 0x41, 0x50, 0x50, 0x01, 0x55, 0x00, 0x00, 0x05,
+ 0x05, 0x05, 0x51, 0x04, 0x01, 0x45, 0x14, 0x11, 0x50, 0x00, 0x41, 0x50,
+ 0x04, 0x10, 0x50, 0x44, 0x00, 0x40, 0x05, 0x50, 0x50, 0x40, 0x01, 0x14,
+ 0xaa, 0xaa, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xa0, 0x82,
+ 0x00, 0x2a, 0xa8, 0x20, 0x28, 0x80, 0x2a, 0x20, 0x08, 0x08, 0xa0, 0x82,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
+ 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0x80, 0x0a, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x54, 0x55, 0x01, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0x02, 0xa0,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x05, 0x40, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xa0, 0xaa, 0x0a, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x50,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x28, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x55, 0x55, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x2a, 0x2a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x15, 0x15, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xaa, 0x8a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x45,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0xa2, 0x22, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x88, 0x00, 0x00, 0x80, 0xaa, 0x2a, 0x0a, 0x00, 0x0a, 0x08,
+ 0x02, 0x22, 0xa0, 0x80, 0x08, 0x00, 0xa0, 0x00, 0x20, 0xa0, 0xa0, 0xa0,
+ 0x41, 0x01, 0x51, 0x45, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01,
+ 0x00, 0x00, 0x55, 0x55, 0x14, 0x00, 0x11, 0x14, 0x05, 0x45, 0x10, 0x41,
+ 0x11, 0x00, 0x40, 0x01, 0x14, 0x41, 0x40, 0x10, 0x82, 0x28, 0xa2, 0xaa,
+ 0x80, 0xa2, 0xa2, 0xa0, 0xa8, 0x00, 0x28, 0x28, 0x08, 0xa2, 0x02, 0xaa,
+ 0xa8, 0x80, 0x20, 0x88, 0x88, 0x0a, 0x08, 0x82, 0x20, 0x00, 0x80, 0x0a,
+ 0x00, 0x82, 0x00, 0x08, 0x04, 0x51, 0x51, 0x55, 0x45, 0x44, 0x11, 0x11,
+ 0x11, 0x01, 0x50, 0x44, 0x04, 0x11, 0x05, 0x55, 0x41, 0x41, 0x40, 0x10,
+ 0x40, 0x55, 0x04, 0x44, 0x40, 0x00, 0x00, 0x14, 0x00, 0x01, 0x01, 0x04,
+ 0x88, 0xa8, 0xa8, 0x2a, 0x2a, 0x20, 0x08, 0x0a, 0x0a, 0x02, 0xa0, 0x80,
+ 0x88, 0x08, 0xa2, 0xaa, 0x02, 0x22, 0x00, 0x08, 0xa0, 0x8a, 0x02, 0x88,
+ 0x20, 0x00, 0x00, 0x20, 0x00, 0x82, 0x20, 0x02, 0x05, 0x55, 0x54, 0x55,
+ 0x44, 0x40, 0x50, 0x51, 0x11, 0x01, 0x04, 0x51, 0x10, 0x51, 0x41, 0x55,
+ 0x05, 0x44, 0x00, 0x10, 0x00, 0x50, 0x54, 0x45, 0x40, 0x00, 0x00, 0x40,
+ 0x50, 0x01, 0x01, 0x54, 0x80, 0x2a, 0xaa, 0x0a, 0x28, 0x28, 0x08, 0x08,
+ 0x08, 0x02, 0x88, 0x88, 0x80, 0x08, 0xa8, 0xaa, 0x0a, 0x28, 0x00, 0x08,
+ 0xa0, 0x02, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80, 0x08, 0x02, 0x02, 0x02,
+ 0x00, 0x15, 0x55, 0x15, 0x44, 0x44, 0x10, 0x11, 0x11, 0x01, 0x04, 0x45,
+ 0x50, 0x10, 0x51, 0x55, 0x15, 0x44, 0x00, 0x10, 0x00, 0x01, 0x04, 0x40,
+ 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x11, 0x04, 0x80, 0x0a, 0xaa, 0x2a,
+ 0x82, 0x22, 0xa0, 0xa0, 0x08, 0x02, 0xa8, 0xa8, 0x20, 0xa0, 0xa8, 0xaa,
+ 0x0a, 0x28, 0x00, 0x08, 0x80, 0x00, 0x02, 0x80, 0x20, 0x00, 0x00, 0x80,
+ 0x02, 0x02, 0x0a, 0x02, 0x00, 0x04, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x15, 0x44, 0x00, 0x10,
+ 0x10, 0x00, 0x04, 0x40, 0x40, 0x00, 0x00, 0x40, 0x04, 0x01, 0x04, 0x04,
+ 0x08, 0x02, 0xa8, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xaa, 0x28, 0x82, 0x00, 0x08, 0xa8, 0x80, 0x08, 0x88,
+ 0x20, 0x00, 0x20, 0x20, 0x02, 0x0a, 0x0a, 0x08, 0x44, 0x00, 0x50, 0x55,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55,
+ 0x51, 0x01, 0x11, 0x10, 0x54, 0x41, 0x10, 0x44, 0x40, 0x00, 0x40, 0x10,
+ 0x04, 0x01, 0x04, 0x10, 0x00, 0x00, 0xa0, 0xaa, 0x0a, 0x00, 0x00, 0x00,
+ 0x00, 0xa0, 0x00, 0x08, 0x00, 0x00, 0x00, 0xaa, 0x08, 0x00, 0x0a, 0x2a,
+ 0x2a, 0x0a, 0xa0, 0xa0, 0xa0, 0x00, 0x20, 0x0a, 0x28, 0x02, 0x00, 0xa0,
+ 0x50, 0x01, 0x50, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
diff --git a/nx-X11/programs/Xserver/hw/nxagent/x2go.xpm b/nx-X11/programs/Xserver/hw/nxagent/x2go.xpm
new file mode 100644
index 000000000..46a74eab9
--- /dev/null
+++ b/nx-X11/programs/Xserver/hw/nxagent/x2go.xpm
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/* */
+/* Copyright 2008 Heinz-M. Graesing <heinz-m.graesing@obviously-nice.de> */
+/* */
+/* NXAGENT, NX protocol compression and NX extensions to this software */
+/* are copyright of the aforementioned persons and companies. */
+/* */
+/* Redistribution and use of the present software is allowed according */
+/* to terms specified in the file LICENSE which comes in the source */
+/* distribution. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+/* XPM */
+static char *x2goagentIconData[]={
+"128 128 17 1",
+". c None",
+"m c #323232",
+"l c #323232",
+"f c #323232",
+"e c #323232",
+"o c #323232",
+"# c #323232",
+"h c #323232",
+"i c #323232",
+"n c #323232",
+"d c #323232",
+"a c #323232",
+"g c #323232",
+"j c #323232",
+"b c #323232",
+"k c #323232",
+"c c #323232",
+".....#abccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccbde.....",
+"...fbccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccgf...",
+"..#ccccaheeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeijccckf..",
+".ecccgl..................................................................................................................ejcckf.",
+".bccd.....................................................................................................................mdccg.",
+"#cca.......................................................................................................................mjcce",
+"gckm........................................................................................................................eccd",
+"ccn..........................................................................................................................jcb",
+"cce..........................................................................................................................icc",
+"ccm..........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc............................................meeee..........................................................................ecc",
+"cc.........eeeeeeeeoiiiiiiiinggggggggjccccccccccccc....#ggggggggggggggggggggggggggggf.............ggggggggggggggggggggggf....ecc",
+"cc....meeeeoiiiiiiiinggggggggjccccccccccccccccccccc....icccccccccccccccccccccccccccce.............cccccccccccccccccccccce....ecc",
+"cc....................................meeeeeeeeoiii....icccccccccccccccccccccccccccce.............cccccccccccccccccccccce....ecc",
+"cc.......................................................menbccccccccccccccccccbhe..................logccccccccccccghe.......ecc",
+"cc...........................................................iccccccccccccccccdm.......................#cccccccccke..........ecc",
+"cc..............................................lee...........#cccccccccccccckm.........................jccccccckm...........ecc",
+"cc........feeeeeeeeoiiiiiiiiiaggggggggjcccccccccccc............icccccccccccccd..........................icccccccf............ecc",
+"cc....meeeeeoiiiiiiiinggggggggjcccccccccccccccccccciiiiii#m.....jcccccccccccci..........................icccccci.............ecc",
+"cc......................................eeeeeeeeeiiiiiiiiigl....eccccccccccccd..........................dcccccj..............ecc",
+"cc...............................................................dcccccccccccj..........................bccccce..............ecc",
+"cc...............................................................lccccccccccccl........................lccccca...............ecc",
+"cc.............................................meeeeeeee#iiiie....dccccccccccch........................icccccl...............ecc",
+"cc.........meeeeeeeeoiiiiiiiinggggggggjccccccccccccccccccccccb....ecccccccccccb........................bccccn................ecc",
+"cc....meeeeiiiiiiiiiaggggggggbcccccccccccccccccccccccccccccccc#....gccccccccccco......................#cccckm................ecc",
+"cc....................................meeeeeeeeeiiiiiiiiiaggggd....#cccccccccccg......................bcccci.................ecc",
+"cc..................................................................bcccccccccccf....................#cccckm.................ecc",
+"cc..................................................................hcccccccccccd...................mkcccci..................ecc",
+"cc............................................meeeeeeeeoiiiiiiiil...mkcccccccccccl..................icccckm..................ecc",
+"cc.........eeeeeeeeoiiiiiiiinggggggggjccccccccccccccccccccccccccn....dccccccccccci.................mkcccci...................ecc",
+"cc....meeeeeiiiiiiiiiaggggggggbccccccccccccccccccccccccccccccccckm...lccccccccccck.................icccckm...................ecc",
+"cc.....................................leeeeeeeeoiiiiiiiiigggggggo....accccccccccc#...............mkcccch....................ecc",
+"cc....................................................................ecccccccccccb...............iccccb.....................ecc",
+"cc.....................................................................jccccccccccce.............mkcccc#.....................ecc",
+"cc.............................................meeeeeeeeehiiiiiiii#....#ccccccccccca.............nccccb......................ecc",
+"cc........feeeeeeee#iiiiiiiiigggggggggkccccccccccccccccccccccccccccl....kcccccccccccl...........lccccc#......................ecc",
+"cc....meeeeeoiiiiiiiiigggggggggkcccccccccccccccccccccccccccccccccccd....icccccccccccd...........dccccb.......................ecc",
+"cc......................................leeeeeeeeoiiiiiiiingggggggga....mccccccccccckm.........lccccc#.......................ecc",
+"cc.......................................................................dccccccccccch.........dccccb........................ecc",
+"cc.......................................................................lcccccccccccb........lccccc#........................ecc",
+"cc.............................................meeeeeeeeoiiiiiiiingggo....gccccccccccc#.......dccccg.........................ecc",
+"cc.........meeeeeeeeoiiiiiiiinggggggggjccccccccccccccccccccccccccccccg....occcccccccccg......lccccce.........................ecc",
+"cc....meeeeiiiiiiiiiaggggggggbcccccccccccccccccccccccccccccccccccccccce....bccccccccccce.....gccccg..........................ecc",
+"cc....................................meeeeeeeeeiiiiiiiiigggggggggkcccd....#cccccccccccd....eccccce..........................ecc",
+"cc.........................................................................mkcccccccccccl...gccccg...........................ecc",
+"cc..........................................................................nccccccccccci..eccccce...........................ecc",
+"cc............................................meeeeeeeeoiiiiiiiingggggggm...lccccccccccckm.gccccg............................ecc",
+"cc.........eeeeeeeeoiiiiiiiinggggggggjcccccccccccccccccccccccccccccccccc#....dccccccccccc#eccccce............................ecc",
+"cc....meeeeeiiiiiiiiiaggggggggkcccccccccccccccccccccccccccccccccccccccccb....ecccccccccccbgccccg.............................ecc",
+"cc.....................................leeeeeeeeoiiiiiiiiigggggggggkccccco....gccccccccccccccccl.............................ecc",
+"cc............................................................................#cccccccccccccccd..............................ecc",
+"cc.............................................................................bccccccccccccccl..............................ecc",
+"cc.............................................leeeeeeeeeiiiiiiiiiagggggggi....icccccccccccccd...............................ecc",
+"cc........feeeeeeee#iiiiiiiingggggggggkccccccccccccccccccccccccccccccccccckm...mkccccccccccccl...............................ecc",
+"cc....meeeeeoiiiiiiiiigggggggggkccccccccccccccccccccccccccccccccccccccccccci....dccccccccccca................................ecc",
+"cc......................................leeeeeeeeoiiiiiiiiigggggggggccccccck....lccccccccccckm...............................ecc",
+"cc...............................................................................accccccccccc#...............................ecc",
+"cc...............................................................................ecccccccccccb...............................ecc",
+"cc............................................leeeeeeeeeiiiiiiiiiaggggggggbcce....bccccccccccce..............................ecc",
+"cc.......feeeeeeee#iiiiiiiiigggggggggkcccccccccccccccccccccccccccccccccccccccd....#cccccccccccg..............................ecc",
+"cc....meeeeeeoiiiiiiiingggggggggccccccccccccccccccccccccccccccccccccccccccccccl....kcccccccccccl.............................ecc",
+"cc.......................................feeeeeeeehiiiiiiiidggggggggbccccccccci....ncccccccccccd.............................ecc",
+"cc...........................................................................mm....bccccccccccccm............................ecc",
+"cc................................................................................#ccccccccccccci............................ecc",
+"cc..........................................leeeeeeee#iiiiiiiidggggggggbcccccl....bccccccccccccck............................ecc",
+"cc......feeeeeeeehiiiiiiiiaggggggggkccccccccccccccccccccccccccccccccccccccccd....#ccccccccccccccc#...........................ecc",
+"cc....meeeeeee#iiiiiiiidggggggggjcccccccccccccccccccccccccccccccccccccccccccl....bcccccccccccccccb...........................ecc",
+"cc.......................................meeeeeeeeeiiiiiiiiigggggggggkcccccd....#cccccbccccccccccce..........................ecc",
+"cc..............................................................................bccccdhcccccccccccg..........................ecc",
+"cc.............................................................................#ccccclmkcccccccccccl.........................ecc",
+"cc..........................................meeeeeeeeeiiiiiiiiiaggggggggbkm....bccccd..ncccccccccccd.........................ecc",
+"cc.....leeeeeeeeoiiiiiiiiigggggggggkccccccccccccccccccccccccccccccccccccci....hcccckl..lccccccccccccm........................ecc",
+"cc....meeeeeeeehiiiiiiiidggggggggbcccccccccccccccccccccccccccccccccccccckm...mkcccci....dccccccccccci........................ecc",
+"cc........................................leeeeeeee#iiiiiiiinggggggggjcci....icccckm....eccccccccccck........................ecc",
+"cc..........................................................................mkcccci......gccccccccccc#.......................ecc",
+"cc..........................................................................icccckm......#cccccccccccb.......................ecc",
+"cc.........................................leeeeeeeeoiiiiiiiiigggggggga....mkcccci........bccccccccccce......................ecc",
+"cc....meeeeeeeeoiiiiiiiiigggggggggkccccccccccccccccccccccccccccccccccci....icccckm........hcccccccccccg......................ecc",
+"cc.....feeeeeeeehiiiiiiiiaggggggggkcccccccccccccccccccccccccccccccccckm...mkcccci.........mkcccccccccccl.....................ecc",
+"cc.........................................feeeeeeeehiiiiiiiiagggggggh....icccckm..........icccccccccccd.....................ecc",
+"cc.......................................................................mkcccci...........lccccccccccccm....................ecc",
+"cc.......................................................................icccckm............dccccccccccci....................ecc",
+"cc...........................................eeeeeeeeehiiiiiiiidggga....mkcccci.............fccccccccccck....................ecc",
+"cc......feeeeeeee#iiiiiiiingggggggggccccccccccccccccccccccccccccccci....iccccb...............gccccccccccc#...................ecc",
+"cc....meeeeeeeoiiiiiiiiigggggggggbcccccccccccccccccccccccccccccccckm...mkcccc#...............occcccccccccb...................ecc",
+"cc........................................meeeeeeeeeiiiiiiiiidgggg#....iccccb.................bccccccccccce..................ecc",
+"cc....................................................................mkcccc#.................#cccccccccccg..................ecc",
+"cc....................................................................iccccb..................mkcccccccccccl.................ecc",
+"cc..........................................eeeeeeeeeiiiiiiiiiaga....mkcccc#...................icccccccccccd.................ecc",
+"cc.....leeeeeeee#iiiiiiiinggggggggjccccccccccccccccccccccccccccci....iccccb....................lccccccccccccm................ecc",
+"cc....meeeeeeee#iiiiiiiiigggggggggkcccccccccccccccccccccccccccckm...mkcccc#.....................dccccccccccci................ecc",
+"cc.........................................leeeeeeeeoiiiiiiiiiah....iccccb......................lccccccccccck................ecc",
+"cc.................................................................mkcccc#.......................gccccccccccc#...............ecc",
+"cc.................................................................dccccj........................ecccccccccccj...............ecc",
+"cc..........................................leeeeeeeeeiiiiiiih....lccccce.........................bccccccccccce..............ecc",
+"cc....meeeeeeeeeiiiiiiiiidgggggggggcccccccccccccccccccccccccci....dccccg..........................#ccccccccccca..............ecc",
+"cc.....feeeeeeeeiiiiiiiinggggggggbcccccccccccccccccccccccccckm...lccccce...........................kcccccccccccl.............ecc",
+"cc........................................leeeeeeeehiiiiiiiih....dccccg............................ncccccccccccd.............ecc",
+"cc..............................................................lccccce............................fccccccccccccf............ecc",
+"cc..............................................................dccccb..............................jcccccccccccg............ecc",
+"cc.........................................meeeeeeeeoiiiiil....lcccccn..............................icccccccccccce...........ecc",
+"cc......feeeeeeeehiiiiiiiigggggggggccccccccccccccccjgggggo.....gccccc#..............................eccccccccccccbm..........ecc",
+"cc....meeeeeeeoiiiiiiiiidgggggggggccccccccccccccccc...........hcccccco...............................cccccccccccccn..........ecc",
+"cc.........................................leeeeeee..........ecccccccn..............................lcccccccccccccc#.........ecc",
+"cc..........................................................#kccccccckf.............................nccccccccccccccc#........ecc",
+"cc........................................................ldcccccccccck#m.........................lncccccccccccccccccdl......ecc",
+"cc.........................................feeeeeee....ogjcccccccccccccccggi..................oggbcccccccccccccccccccccja....ecc",
+"cc.....leeeeeeee#iiiiiiiidggggggggbcccccccccccccccc....icccccccccccccccccccg..................icccccccccccccccccccccccccc....ecc",
+"cc....meeeeeeeehiiiiiiiiaggggggggkccccccccccccccccc....icccccccccccccccccccg..................icccccccccccccccccccccccccc....ecc",
+"cc........................................feeeeeeee..........................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cc...........................................................................................................................ecc",
+"cce..........................................................................................................................hcc",
+"ccn..........................................................................................................................acb",
+"jcb.........................................................................................................................lcca",
+"hcci........................................................................................................................acc#",
+"mkcc#......................................................................................................................dccb.",
+".occci...................................................................................................................macccf.",
+"..#cccbne.............................................................................................................menkccc#..",
+"...okccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccbe...",
+"....mhjccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccg#....."};