1
0
xorg-x11-server/xorg-server-xf4vnc.patch

23841 lines
706 KiB
Diff
Raw Normal View History

Index: xorg-server-1.6.3.901/Makefile.am
================================================================================
--- xorg-server-1.7.4/Makefile.am
+++ xorg-server-1.7.4/Makefile.am
@@ -17,6 +17,10 @@
RECORD_DIR=record
endif
+if XCLIPLIST
+XCLIPLIST_DIR=xcliplist
+endif
+
SUBDIRS = \
doc \
include \
@@ -36,6 +40,7 @@
damageext \
$(COMPOSITE_DIR) \
$(GLX_DIR) \
+ $(XCLIPLIST_DIR) \
exa \
config \
hw \
--- xorg-server-1.7.4/configure.ac
+++ xorg-server-1.7.4/configure.ac
@@ -611,6 +611,8 @@
dnl DDXes.
AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
+AC_ARG_ENABLE(xcliplist, AS_HELP_STRING([--enable-xcliplist], [Build XClipList extension (default: auto)]), [XCLIPLIST=$enableval], [XCLIPLIST=auto])
+AC_ARG_ENABLE(vnc, AS_HELP_STRING([--enable-vnc], [Build Xvnc server (default: yes)]), [VNC=$enableval], [VNC=auto])
AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto])
AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes])
AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto])
@@ -1091,6 +1093,20 @@
AM_CONDITIONAL(VBE, test "x$VBE" = xyes)
AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes)
+if test "x$XCLIPLIST" = xauto; then
+ if test "x$XORG" = xno; then
+ XCLIPLIST=no
+ else
+ PKG_CHECK_MODULES([XCLIPLIST], [xcliplistproto xcliplist], [XCLIPLIST=yes], [XCLIPLIST=no])
+ fi
+fi
+AM_CONDITIONAL(XCLIPLIST, [test "x$XCLIPLIST" = xyes])
+if test "x$XCLIPLIST" = xyes; then
+ AC_DEFINE(XCLIPLIST, 1, [Support XClipList extension])
+ REQUIRED_MODULES="$REQUIRED_MODULES xcliplistproto"
+ XCLIPLIST_LIB='$(top_builddir)/xcliplist/libxcliplist.la'
+fi
+
AC_DEFINE(SHAPE, 1, [Support SHAPE extension])
AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data])
@@ -1373,6 +1389,40 @@
dnl DDX section.
dnl ---------------------------------------------------------------------------
+dnl VNC DDX
+
+AC_MSG_CHECKING([whether to build Xvnc DDX])
+PKG_CHECK_MODULES([VNCMODULES], [xmuu xext x11 xrender xfont xi vncproto xau $XDMCP_MODULES $PIXMAN], [have_vnc=yes], [have_vnc=no])
+if test "x$VNC" = xauto; then
+ VNC="$have_vnc"
+fi
+AC_MSG_RESULT([$VNC])
+AM_CONDITIONAL(VNC, [test "x$VNC" = xyes])
+
+if test "x$VNC" = xyes; then
+ if test "x$have_vnc" = xno; then
+ AC_MSG_ERROR([Xvnc build explicitly requested, but required
+ modules not found.])
+ fi
+ XVNC_CFLAGS="-DVNCSERVER -DHAVE_XVNC_CONFIG_H"
+ AC_SUBST([XVNC_CFLAGS])
+ VNC_INCLUDES="$XEXT_INC $RENDER_INC $XTRAP_INC $RECORD_INC"
+ XVNC_LIBS="$CONFIG_LIB $XSERVER_LIBS $FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $XTRAP_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $XPSTUBS_LIB $CWRAP_LIB $OS_LIB $LIBS"
+ AC_SUBST([XVNC_LIBS])
+
+ if test "x$GLX" = xyes; then
+ PKG_CHECK_MODULES([GL], [glproto])
+ fi
+ PKG_CHECK_MODULES([XVNCCONFIG_DEP], [xaw7 xmu xt xpm x11])
+ AC_SUBST(XVNCCONFIG_DEP_CFLAGS)
+ AC_SUBST(XVNCCONFIG_DEP_LIBS)
+ ${CONFIG_SHELL-/bin/sh} $srcdir/hw/vnc/symlink-vnc.sh \
+ $srcdir/hw/vnc $srcdir/hw/xfree86/vnc && \
+ ${CONFIG_SHELL-/bin/sh} $srcdir/hw/vnc/symlink-vnc.sh \
+ $srcdir/hw/vnc $srcdir/hw/dmx/vnc || \
+ AC_MSG_ERROR([Failed symlinking VNC sources])
+fi
+
dnl Xvfb DDX
AC_MSG_CHECKING([whether to build Xvfb DDX])
@@ -2065,6 +2115,7 @@
Xi/Makefile
xfixes/Makefile
exa/Makefile
+xcliplist/Makefile
hw/Makefile
hw/xfree86/Makefile
hw/xfree86/common/Makefile
@@ -2098,6 +2149,7 @@
hw/xfree86/shadowfb/Makefile
hw/xfree86/vbe/Makefile
hw/xfree86/vgahw/Makefile
+hw/xfree86/vnc/Makefile
hw/xfree86/x86emu/Makefile
hw/xfree86/xaa/Makefile
hw/xfree86/xf8_16bpp/Makefile
@@ -2109,8 +2161,10 @@
hw/dmx/examples/Makefile
hw/dmx/input/Makefile
hw/dmx/glxProxy/Makefile
+hw/dmx/vnc/Makefile
hw/dmx/Makefile
hw/vfb/Makefile
+hw/vnc/Makefile
hw/xnest/Makefile
hw/xwin/Makefile
hw/xquartz/Makefile
--- xorg-server-1.7.4/hw/Makefile.am
+++ xorg-server-1.7.4/hw/Makefile.am
@@ -22,6 +22,10 @@
KDRIVE_SUBDIRS = kdrive
endif
+if VNC
+VNC_SUBDIRS = vnc
+endif
+
if XQUARTZ
XQUARTZ_SUBDIRS = xquartz
endif
@@ -32,10 +36,11 @@
$(XVFB_SUBDIRS) \
$(XNEST_SUBDIRS) \
$(DMX_SUBDIRS) \
+ $(VNC_SUBDIRS) \
$(KDRIVE_SUBDIRS) \
$(XQUARTZ_SUBDIRS)
-DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
+DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive vnc
relink:
for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink ; done
--- xorg-server-1.7.4/hw/dmx/Makefile.am
+++ xorg-server-1.7.4/hw/dmx/Makefile.am
@@ -1,6 +1,6 @@
-DIST_SUBDIRS = input config glxProxy examples doc
+DIST_SUBDIRS = input vnc config glxProxy examples doc
-SUBDIRS = input config examples
+SUBDIRS = input vnc config examples
bin_PROGRAMS = Xdmx
if XINERAMA
--- xorg-server-1.7.4/hw/dmx/dmx-config.h
+++ xorg-server-1.7.4/hw/dmx/dmx-config.h
@@ -72,4 +72,7 @@
/* Enable the DMX extension */
#define DMXEXT
+/* Enable VNC ability */
+#define DMXVNC 1
+
#endif /* DMX_CONFIG_H */
--- xorg-server-1.7.4/hw/dmx/dmxinit.c
+++ xorg-server-1.7.4/hw/dmx/dmxinit.c
@@ -79,6 +79,10 @@
);
#endif /* GLXEXT */
+#ifdef DMXVNC
+extern void VNCInitForDMX(void);
+#endif
+
/* Global variables available to all Xserver/hw/dmx routines. */
int dmxNumScreens;
DMXScreenInfo *dmxScreens;
@@ -807,6 +811,9 @@
dmxLog(dmxInfo, "Shadow framebuffer support %s\n",
dmxShadowFB ? "enabled" : "disabled");
+#ifdef DMXVNC
+ VNCInitForDMX();
+#endif
}
/* RATS: Assuming the fp string (which comes from the command-line argv
@@ -1033,3 +1040,14 @@
ErrorF(" Ctrl-Alt-q Quit (core devices only)\n");
ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n");
}
+
+#ifdef DDXTIME
+/** Return wall-clock time in milliseconds. */
+CARD32 GetTimeInMillis(void)
+{
+ struct timeval tp;
+
+ gettimeofday(&tp, 0);
+ return tp.tv_sec * 1000 + tp.tv_usec / 1000;
+}
+#endif
--- xorg-server-1.7.4/hw/dmx/dmxsync.c
+++ xorg-server-1.7.4/hw/dmx/dmxsync.c
@@ -99,9 +99,16 @@
TimerForce(dmxSyncTimer);
}
+#ifdef DMXVNC
+extern void rfbWakeupHandlerDMX(void);
+#endif
+
static void dmxSyncWakeupHandler(pointer blockData, int result,
pointer pReadMask)
{
+#ifdef DMXVNC
+ rfbWakeupHandlerDMX();
+#endif
}
/** Request the XSync() batching optimization with the specified \a
--- xorg-server-1.7.4/hw/dmx/input/Makefile.am
+++ xorg-server-1.7.4/hw/dmx/input/Makefile.am
@@ -61,6 +61,7 @@
AM_CFLAGS = $(DIX_CFLAGS) \
-I$(top_srcdir)/hw/dmx \
-DHAVE_DMX_CONFIG_H \
+ -DDMXVNC=1 \
$(GLX_DEFS) \
@DMXMODULES_CFLAGS@
--- xorg-server-1.7.4/hw/dmx/input/dmxcommon.c
+++ xorg-server-1.7.4/hw/dmx/input/dmxcommon.c
@@ -648,7 +648,6 @@
dmxLogInput(dmxInput, "Keyboard busy, waiting\n");
else
dmxLogInput(dmxInput, "Keyboard error, waiting\n");
-
/* Don't generate X11 protocol for a bit */
for (tmp = GetTimeInMillis(); GetTimeInMillis() - tmp < 250;) {
usleep(250); /* This ends up sleeping only until
--- xorg-server-1.7.4/hw/dmx/input/dmxinputinit.c
+++ xorg-server-1.7.4/hw/dmx/input/dmxinputinit.c
@@ -372,6 +372,11 @@
static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info)
{
GETDMXINPUTFROMPDEVICE;
+
+#ifdef DMXVNC
+ vncSetKeyboardDevice(pDevice);
+#endif
+
XkbRMLVOSet rmlvo;
rmlvo.rules = dmxConfigGetXkbRules();
@@ -451,7 +456,9 @@
}
if (info.keyClass) {
XkbRMLVOSet rmlvo;
-
+#ifdef DMXVNC
+ vncSetKeyboardDevice(pDevice);
+#endif
rmlvo.rules = dmxConfigGetXkbRules();
rmlvo.model = dmxConfigGetXkbModel();
rmlvo.layout = dmxConfigGetXkbLayout();
@@ -499,6 +506,9 @@
info.res[i], info.minres[i],
info.maxres[i]);
}
+#ifdef DMXVNC
+ vncSetPointerDevice(pDevice);
+#endif
}
if (info.focusClass) InitFocusClassDeviceStruct(pDevice);
if (info.proximityClass) InitProximityClassDeviceStruct(pDevice);
--- xorg-server-1.7.4/hw/dmx/input/dmxinputinit.h
+++ xorg-server-1.7.4/hw/dmx/input/dmxinputinit.h
@@ -288,4 +288,9 @@
extern int dmxInputAttachBackend(int physicalScreen, int isCore,
int *id);
+#ifdef DMXVNC
+extern void vncSetKeyboardDevice(DeviceIntPtr kbd);
+extern void vncSetPointerDevice(DeviceIntPtr ptr);
+#endif
+
#endif
--- xorg-server-1.7.4/hw/dmx/vnc/.gitignore
+++ xorg-server-1.7.4/hw/dmx/vnc/.gitignore
@@ -0,0 +1,36 @@
+auth.c
+cmap.c
+corre.c
+cursor.c
+cutpaste.c
+d3des.c
+d3des.h
+dispcur.c
+draw.c
+hextile.c
+httpd.c
+kbdptr.c
+keyboard.h
+loginauth.c
+rdp.c
+rfb.h
+rfbkeyb.c
+rfbmouse.c
+rfbproto.h
+rfbserver.c
+rre.c
+sockets.c
+sprite.c
+sprite.h
+spritest.h
+stats.c
+tableinitcmtemplate.c
+tableinittctemplate.c
+tabletranstemplate.c
+tight.c
+translate.c
+vncauth.c
+vncauth.h
+vncext.c
+xistubs.c
+zlib.c
--- xorg-server-1.7.4/hw/dmx/vnc/Makefile.am
+++ xorg-server-1.7.4/hw/dmx/vnc/Makefile.am
@@ -0,0 +1,43 @@
+noinst_LIBRARIES = libdmxvnc.a
+
+SRCS = \
+ auth.c \
+ cmap.c \
+ corre.c \
+ cursor.c \
+ cutpaste.c \
+ d3des.c \
+ dispcur.c \
+ draw.c \
+ hextile.c \
+ httpd.c \
+ kbdptr.c \
+ loginauth.c \
+ rdp.c \
+ rfbkeyb.c \
+ rfbmouse.c \
+ rfbserver.c \
+ rre.c \
+ sockets.c \
+ sprite.c \
+ stats.c \
+ tight.c \
+ translate.c \
+ vncauth.c \
+ vncext.c \
+ vncInit.c \
+ xistubs.c \
+ zlib.c
+
+
+libdmxvnc_a_SOURCES = $(SRCS)
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/hw/dmx \
+ -I$(top_srcdir)/hw/xfree86/common \
+ -DHAVE_DMX_CONFIG_H \
+ $(DIX_CFLAGS) \
+ -DDMXVNC=1 \
+ @DMXMODULES_CFLAGS@
+
+###EXTRA_DIST = dmxdetach.c
--- xorg-server-1.7.4/hw/dmx/vnc/vncInit.c
+++ xorg-server-1.7.4/hw/dmx/vnc/vncInit.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+#include "rfb.h"
+
+#ifdef HAVE_DMX_CONFIG_H
+#include "dmx-config.h"
+#endif
+
+#ifdef DMXVNC
+#include "../dmx.h"
+#include "../dmxcb.h"
+#endif
+
+#include <time.h>
+#include "fb.h"
+
+#include "dixstruct.h"
+#include "compiler.h"
+
+#include "mipointer.h"
+#include "mibstore.h"
+
+#include "globals.h"
+#define DPMS_SERVER
+#include <X11/extensions/dpms.h>
+
+#include <netinet/in.h>
+
+int vncScreenPrivateIndex = -1;
+int rfbGCIndex = -1;
+int inetdSock = -1;
+Atom VNC_LAST_CLIENT_ID = 0;
+Atom VNC_CONNECT = 0;
+char *desktopName = "x11";
+char rfbThisHost[256];
+
+extern void VncExtensionInit(void);
+
+extern void vncInitMouse(void);
+extern void vncInitKeyb(void);
+Bool VNCInit(ScreenPtr pScreen, DMXScreenInfo *dmxScreen);
+
+#ifndef XFree86LOADER
+static unsigned long VNCGeneration = 0;
+#endif
+static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask);
+
+/*
+ * rfbLog prints a time-stamped message to the log file (stderr).
+ */
+
+void rfbLog(char *format, ...)
+{
+ va_list args;
+ char buf[256];
+ time_t clock;
+
+ va_start(args, format);
+
+ time(&clock);
+ strftime(buf, 255, "%d/%m/%Y %H:%M:%S ", localtime(&clock));
+ fprintf(stderr, buf);
+
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+
+ va_end(args);
+}
+
+void rfbLogPerror(char *str)
+{
+ rfbLog("");
+ perror(str);
+}
+
+
+static ScreenPtr TheVNCScreen = NULL;
+
+
+static void
+nopGetImage(DrawablePtr pDrawable, int sx, int sy,
+ int w, int h, unsigned int format,
+ unsigned long planemask, char *pdstLine)
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+
+ (*pScreen->GetImage)(pDrawable,sx,sy,w,h,format,planemask,pdstLine);
+}
+
+
+static void
+SetupVNCScreen(void)
+{
+ vncScreenPtr pScreenPriv;
+ VisualPtr v = NULL;
+ int i;
+
+ pScreenPriv = xalloc(sizeof(vncScreenRec));
+ pScreenPriv->width = dmxGlobalWidth;
+ pScreenPriv->height = dmxGlobalHeight;
+ pScreenPriv->rfbAuthTries = 0;
+ pScreenPriv->rfbAuthTooManyTries = FALSE;
+ pScreenPriv->timer = NULL;
+ pScreenPriv->udpPort = 0;
+ pScreenPriv->rfbListenSock = -1;
+ pScreenPriv->udpSock = -1;
+ pScreenPriv->udpSockConnected = FALSE;
+ pScreenPriv->httpListenSock = -1;
+ pScreenPriv->httpSock = -1;
+ pScreenPriv->maxFd = 0;
+ pScreenPriv->rfbAuthPasswdFile = NULL;
+ pScreenPriv->httpDir = NULL;
+ pScreenPriv->rfbInstalledColormap = NULL;
+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY);
+
+ pScreenPriv->rfbPort = 0;
+ pScreenPriv->httpPort = 0;
+ pScreenPriv->rfbAuthPasswdFile = NULL;
+ pScreenPriv->httpDir = NULL;
+ pScreenPriv->rfbAlwaysShared = FALSE;
+ pScreenPriv->rfbNeverShared = FALSE;
+ pScreenPriv->rfbUserAccept = FALSE;
+ pScreenPriv->rfbViewOnly = FALSE;
+ pScreenPriv->rfbDontDisconnect = FALSE;
+ pScreenPriv->loginAuthEnabled = FALSE;
+
+ /* Find the root window's visual.
+ * XXX this might be the wrong info to use below.
+ */
+ for (i = 0; i < screenInfo.screens[0]->numVisuals; i++) {
+ v = screenInfo.screens[0]->visuals + i;
+ if (v->vid == screenInfo.screens[0]->rootVisual) {
+ break;
+ }
+ }
+
+ /* XXX is this the right depth and bpp? */
+ /* With DMX, screenInfo.screens[0]->rootDepth is 24 and that doesn't
+ * work in translate.c! We're just using 32.
+ */
+ pScreenPriv->rfbServerFormat.bitsPerPixel = 32;
+ pScreenPriv->rfbServerFormat.depth = 32;
+ pScreenPriv->rfbServerFormat.bigEndian = 0;
+ pScreenPriv->rfbServerFormat.trueColour = (v->class == TrueColor);
+ if (pScreenPriv->rfbServerFormat.trueColour) {
+ pScreenPriv->rfbServerFormat.redMax = v->redMask >> v->offsetRed;
+ pScreenPriv->rfbServerFormat.greenMax = v->greenMask >> v->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueMax = v->blueMask >> v->offsetBlue;
+ pScreenPriv->rfbServerFormat.redShift = v->offsetRed;
+ pScreenPriv->rfbServerFormat.greenShift = v->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueShift = v->offsetBlue;
+ } else {
+ pScreenPriv->rfbServerFormat.redMax
+ = pScreenPriv->rfbServerFormat.greenMax
+ = pScreenPriv->rfbServerFormat.blueMax = 0;
+ pScreenPriv->rfbServerFormat.redShift
+ = pScreenPriv->rfbServerFormat.greenShift
+ = pScreenPriv->rfbServerFormat.blueShift = 0;
+ }
+
+ /* Allocate/init TheVNCScreen object */
+ vncScreenPrivateIndex = 0;
+
+ TheVNCScreen = (ScreenPtr) Xcalloc(1, sizeof(struct _Screen));
+ TheVNCScreen->devPrivates = (DevUnion *) Xcalloc(1, sizeof(DevUnion));
+ TheVNCScreen->devPrivates[vncScreenPrivateIndex].ptr = pScreenPriv;
+ TheVNCScreen->GetImage = nopGetImage;
+
+ rfbInitSockets(TheVNCScreen);
+ if (inetdSock == -1)
+ httpInitSockets(TheVNCScreen);
+}
+
+
+/*
+ * Called by DMX's InitOutput()
+ * Will be called for each X server generation.
+ */
+void
+VNCInitForDMX(void)
+{
+ rfbLog("DMXVNC: Initializing VNC for DMX\n");
+ ErrorF("DMXVNC: Initializing VNC for DMX\n");
+
+ if (TheVNCScreen) {
+ rfbLog("DMXVNC: New server generation\n");
+ }
+ else {
+ rfbLog("DMXVNC: Set up VNC screen\n");
+ SetupVNCScreen();
+ }
+
+ /* Reset the input device pointers. They'll get set later.
+ * This allows successful server regeneration.
+ */
+ vncSetKeyboardDevice(NULL);
+ vncSetPointerDevice(NULL);
+}
+
+
+Bool
+VNCInit(ScreenPtr pScreen, DMXScreenInfo *pScrn)
+{
+ VisualPtr visual;
+ vncScreenPtr pScreenPriv;
+#if 0
+ char *interface_str = NULL;
+#endif
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
+
+#ifndef XFree86LOADER
+ if (VNCGeneration != serverGeneration) {
+ VNCGeneration = serverGeneration;
+ if ( ((vncScreenPrivateIndex = AllocateScreenPrivateIndex()) < 0) ||
+ ((rfbGCIndex = AllocateGCPrivateIndex()) < 0) )
+ return FALSE;
+ }
+#endif
+
+ if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) {
+ ErrorF("VNCInit(): failed to allocate GCIndex\n");
+ return FALSE;
+ }
+
+ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec))))
+ return FALSE;
+
+ pScreen->devPrivates[vncScreenPrivateIndex].ptr = (pointer)pScreenPriv;
+
+ pScreenPriv->rfbAuthTries = 0;
+ pScreenPriv->rfbAuthTooManyTries = FALSE;
+ pScreenPriv->timer = NULL;
+ pScreenPriv->udpPort = 0;
+ pScreenPriv->rfbListenSock = -1;
+ pScreenPriv->udpSock = -1;
+ pScreenPriv->udpSockConnected = FALSE;
+ pScreenPriv->httpListenSock = -1;
+ pScreenPriv->httpSock = -1;
+ pScreenPriv->maxFd = 0;
+ pScreenPriv->rfbAuthPasswdFile = NULL;
+ pScreenPriv->httpDir = NULL;
+ pScreenPriv->rfbInstalledColormap = NULL;
+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY);
+
+ pScreenPriv->rfbPort = 0;
+ pScreenPriv->httpPort = 0;
+ pScreenPriv->rfbAuthPasswdFile = NULL;
+ pScreenPriv->httpDir = NULL;
+ pScreenPriv->rfbAlwaysShared = FALSE;
+ pScreenPriv->rfbNeverShared = FALSE;
+ pScreenPriv->rfbUserAccept = FALSE;
+ pScreenPriv->rfbViewOnly = FALSE;
+ pScreenPriv->rfbDontDisconnect = FALSE;
+ pScreenPriv->loginAuthEnabled = FALSE;
+
+#if 0
+ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE))
+ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK);
+
+ interface_str = xf86GetOptValString(options, OPTION_INTERFACE);
+
+ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) {
+ Bool failed = FALSE;
+ struct in_addr got;
+ unsigned long octet;
+ char *p = interface_str, *end;
+ int q;
+
+ for (q = 0; q < 4; q++) {
+ octet = strtoul (p, &end, 10);
+
+ if (p == end || octet > 255)
+ failed = TRUE;
+
+ if ((q < 3 && *end != '.') ||
+ (q == 3 && *end != '\0'))
+ failed = TRUE;
+
+ got.s_addr = (got.s_addr << 8) | octet;
+ p = end + 1;
+ }
+
+ if (!failed)
+ pScreenPriv->interface.s_addr = htonl (got.s_addr);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n");
+ }
+#endif
+
+ if (!VNC_LAST_CLIENT_ID)
+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID",
+ strlen("VNC_LAST_CLIENT_ID"), TRUE);
+ if (!VNC_CONNECT)
+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE);
+
+ rfbInitSockets(pScreen);
+ if (inetdSock == -1)
+ httpInitSockets(pScreen);
+
+#ifdef CORBA
+ initialiseCORBA(argc, argv, desktopName);
+#endif
+
+ pScreenPriv->width = pScrn->scrnWidth;
+ pScreenPriv->height = pScrn->scrnHeight;
+ pScreenPriv->depth = pScrn->beDepth;
+ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->scrnWidth, pScrn->beDepth);
+ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->beDepth);
+ pScreenPriv->pfbMemory = NULL;
+ pScreenPriv->oldpfbMemory = NULL;
+
+ pScreenPriv->cursorIsDrawn = TRUE;
+ pScreenPriv->dontSendFramebufferUpdate = FALSE;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->CreateGC = pScreen->CreateGC;
+ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
+ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
+ pScreenPriv->CopyWindow = pScreen->CopyWindow;
+ pScreenPriv->ClearToBackground = pScreen->ClearToBackground;
+ pScreenPriv->RestoreAreas = pScreen->RestoreAreas;
+ pScreenPriv->WakeupHandler = pScreen->WakeupHandler;
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreenPriv->UninstallColormap = pScreen->UninstallColormap;
+ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps;
+ pScreenPriv->StoreColors = pScreen->StoreColors;
+#ifdef CHROMIUM
+ pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
+ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
+ pScreenPriv->PositionWindow = pScreen->PositionWindow;
+ pScreenPriv->ResizeWindow = pScreen->ResizeWindow;
+ pScreenPriv->ClipNotify = pScreen->ClipNotify;
+#endif
+#ifdef RENDER
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ pScreenPriv->Composite = ps->Composite;
+#endif
+ pScreen->CloseScreen = rfbCloseScreen;
+ pScreen->CreateGC = rfbCreateGC;
+ pScreen->PaintWindowBackground = rfbPaintWindowBackground;
+ pScreen->PaintWindowBorder = rfbPaintWindowBorder;
+ pScreen->CopyWindow = rfbCopyWindow;
+ pScreen->ClearToBackground = rfbClearToBackground;
+ pScreen->RestoreAreas = rfbRestoreAreas;
+ pScreen->WakeupHandler = rfbWakeupHandler;
+ pScreen->InstallColormap = rfbInstallColormap;
+ pScreen->UninstallColormap = rfbUninstallColormap;
+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
+ pScreen->StoreColors = rfbStoreColors;
+
+#ifdef CHROMIUM
+ pScreen->RealizeWindow = rfbRealizeWindow;
+ pScreen->UnrealizeWindow = rfbUnrealizeWindow;
+ pScreen->DestroyWindow = rfbDestroyWindow;
+ pScreen->PositionWindow = rfbPositionWindow;
+ pScreen->ResizeWindow = rfbResizeWindow;
+ pScreen->ClipNotify = rfbClipNotify;
+#endif
+#ifdef RENDER
+ if (ps)
+ ps->Composite = rfbComposite;
+#endif
+
+ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++)
+ ;
+
+ if (!visual) {
+ ErrorF("rfbScreenInit: couldn't find root visual\n");
+ return FALSE;
+ }
+
+ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->beBPP;
+ pScreenPriv->rfbServerFormat.depth = pScrn->beDepth;
+ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
+ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor);
+ if (pScreenPriv->rfbServerFormat.trueColour) {
+ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed;
+ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue;
+ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed;
+ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue;
+ } else {
+ pScreenPriv->rfbServerFormat.redMax
+ = pScreenPriv->rfbServerFormat.greenMax
+ = pScreenPriv->rfbServerFormat.blueMax = 0;
+ pScreenPriv->rfbServerFormat.redShift
+ = pScreenPriv->rfbServerFormat.greenShift
+ = pScreenPriv->rfbServerFormat.blueShift = 0;
+ }
+
+ return TRUE;
+}
+
+static void
+rfbWakeupHandler (
+ int i,
+ pointer blockData,
+ unsigned long err,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ /*DMXScreenInfo *pScrn = &dmxScreens[pScreen->myNum];*/
+
+ rfbRootPropertyChange(pScreen); /* Check clipboard */
+
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+#ifdef CORBA
+ corbaCheckFds();
+#endif
+
+ pScreen->WakeupHandler = pScreenPriv->WakeupHandler;
+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask);
+ pScreen->WakeupHandler = rfbWakeupHandler;
+}
+
+
+/**
+ * The rfb wake-up handler used when we're compiled into the DMX server.
+ */
+void
+rfbWakeupHandlerDMX(void)
+{
+ ScreenPtr pScreen = TheVNCScreen;
+ rfbRootPropertyChange(pScreen); /* Check clipboard */
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+}
--- xorg-server-1.7.4/hw/dmx/vnc/vncint.h
+++ xorg-server-1.7.4/hw/dmx/vnc/vncint.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+#ifndef _VNCINT_H_
+#define _VNCINT_H_
+
+#include <netinet/in.h>
+
+extern int vncScreenPrivateIndex;
+
+#define VNCPTR(pScreen)\
+ (vncScreenPtr)((pScreen)->devPrivates[vncScreenPrivateIndex].ptr)
+
+typedef struct {
+ int rfbPort;
+ int rdpPort;
+ int udpPort;
+ int rfbListenSock;
+ int rdpListenSock;
+ int udpSock;
+ int httpPort;
+ int httpListenSock;
+ int httpSock;
+ char * httpDir;
+ char buf[HTTP_BUF_SIZE];
+ Bool udpSockConnected;
+ char * rfbAuthPasswdFile;
+ size_t buf_filled;
+ int maxFd;
+ fd_set allFds;
+ unsigned char * oldpfbMemory;
+ Bool rfbAlwaysShared;
+ Bool rfbNeverShared;
+ Bool rfbDontDisconnect;
+ Bool rfbUserAccept;
+ Bool rfbViewOnly;
+ unsigned char * pfbMemory;
+ int paddedWidthInBytes;
+ ColormapPtr rfbInstalledColormap;
+ ColormapPtr savedColormap;
+ rfbPixelFormat rfbServerFormat;
+ Bool rfbAuthTooManyTries;
+ int rfbAuthTries;
+ Bool loginAuthEnabled;
+ struct in_addr interface;
+ OsTimerPtr timer;
+ unsigned char updateBuf[UPDATE_BUF_SIZE];
+ int ublen;
+ int width;
+ int height;
+ int depth;
+ int bitsPerPixel;
+
+ /* The following two members are used to minimise the amount of unnecessary
+ drawing caused by cursor movement. Whenever any drawing affects the
+ part of the screen where the cursor is, the cursor is removed first and
+ then the drawing is done (this is what the sprite routines test for).
+ Afterwards, however, we do not replace the cursor, even when the cursor
+ is logically being moved across the screen. We only draw the cursor
+ again just as we are about to send the client a framebuffer update.
+
+ We need to be careful when removing and drawing the cursor because of
+ their relationship with the normal drawing routines. The drawing
+ routines can invoke the cursor routines, but also the cursor routines
+ themselves end up invoking drawing routines.
+
+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by
+ doing a CopyArea from a pixmap to the screen, where the pixmap contains
+ the saved contents of the screen under the cursor. Before doing this,
+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
+ (recursively!) remove the cursor before doing it.
+
+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to
+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so
+ that PushPixels doesn't think it has to remove the cursor first.
+ Obviously cursorIsDrawn is set to TRUE afterwards.
+
+ Another problem we face is that drawing routines sometimes cause a
+ framebuffer update to be sent to the RFB client. When the RFB client is
+ already waiting for a framebuffer update and some drawing to the
+ framebuffer then happens, the drawing routine sees that the client is
+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is
+ called. However, if the original drawing routine was actually called
+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
+ want this to happen. So both the cursor routines set
+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check
+ this before calling rfbSendFramebufferUpdate. */
+
+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
+ cursor */
+
+ /* wrapped screen functions */
+
+ CloseScreenProcPtr CloseScreen;
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ RestoreAreasProcPtr RestoreAreas;
+ ScreenWakeupHandlerProcPtr WakeupHandler;
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ ListInstalledColormapsProcPtr ListInstalledColormaps;
+ StoreColorsProcPtr StoreColors;
+ DisplayCursorProcPtr DisplayCursor;
+ CursorPtr pCurs;
+ Bool (*UseHWCursor)(ScreenPtr, CursorPtr);
+ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr);
+ Bool *SWCursor;
+#ifdef CHROMIUM
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ PositionWindowProcPtr PositionWindow;
+ ClipNotifyProcPtr ClipNotify;
+#endif
+#ifdef RENDER
+ CompositeProcPtr Composite;
+#endif
+
+} vncScreenRec, *vncScreenPtr;
+
+extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
+extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
+
+extern void
+rfbSendChromiumStart(unsigned int ipaddress, unsigned int port);
+
+#endif /* _VNCINT_H_ */
+
--- xorg-server-1.7.4/hw/vnc/LICENCE.TXT
+++ xorg-server-1.7.4/hw/vnc/LICENCE.TXT
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- xorg-server-1.7.4/hw/vnc/Makefile.am
+++ xorg-server-1.7.4/hw/vnc/Makefile.am
@@ -0,0 +1,54 @@
+# XXX This Makefile.am probably needs some work.
+
+bin_PROGRAMS = Xvnc
+
+Xvnc_SOURCES = \
+ $(top_srcdir)/fb/fbcmap_mi.c \
+ $(top_srcdir)/mi/miinitext.c \
+ auth.c \
+ cmap.c \
+ corre.c \
+ cursor.c \
+ cutpaste.c \
+ d3des.c \
+ dispcur.c \
+ dpmsstubs.c \
+ draw.c \
+ hextile.c \
+ httpd.c \
+ init.c \
+ kbdptr.c \
+ loginauth.c \
+ rfbkeyb.c \
+ rfbmouse.c \
+ rfbserver.c \
+ rre.c \
+ sprite.c \
+ sockets.c \
+ stats.c \
+ tight.c \
+ translate.c \
+ vncauth.c \
+ vncext.c \
+ xistubs.c \
+ zlib.c
+
+
+JPEG_LIBS = -ljpeg
+CRYPT_LIBS = -lcrypt
+FB_LIBS = ../../fb/.libs/libfb.a
+
+AM_CFLAGS = $(DIX_CFLAGS) $(XVNC_CFLAGS) -I$(top_srcdir)/hw/dmx/vnc -DCHROMIUM=1
+
+Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
+Xvnc_LDADD = \
+ $(XORG_CORE_LIBS) \
+ $(XVNC_LIBS) \
+ $(JPEG_LIBS) \
+ $(CRYPT_LIBS) \
+ $(XSERVER_SYS_LIBS) \
+ $(VNCMODULES_LIBS)
+
+
+relink:
+ rm -f Xvnc && $(MAKE) Xvnc
--- xorg-server-1.7.4/hw/vnc/README
+++ xorg-server-1.7.4/hw/vnc/README
@@ -0,0 +1,14 @@
+
+This is the directory containing the code specific to the TightVNC X server (Xvnc).
+Note that within this directory the name RFB is still used instead of VNC.
+
+NOTE:
+
+The is the new XFree86 v4 architecture VNC server code.
+
+Modified entirely by Alan Hourihane <alanh@fairlite.demon.co.uk>
+
+For information please visit http://xf4vnc.sourceforge.net
+
+Moved to X.org modular tree by Brian Paul.
+
--- xorg-server-1.7.4/hw/vnc/auth.c
+++ xorg-server-1.7.4/hw/vnc/auth.c
@@ -0,0 +1,566 @@
+/*
+ * auth.c - deal with authentication.
+ *
+ * This file implements authentication when setting up an RFB connection.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2003-2004 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "rfb.h"
+#include "windowstr.h"
+
+static void rfbSendSecurityType(rfbClientPtr cl, int securityType);
+static void rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType);
+static void rfbSendTunnelingCaps(rfbClientPtr cl);
+static void rfbSendAuthCaps(rfbClientPtr cl);
+static void rfbVncAuthSendChallenge(rfbClientPtr cl);
+
+/*
+ * rfbAuthNewClient is called right after negotiating the protocol
+ * version. Depending on the protocol version, we send either a code
+ * for authentication scheme to be used (protocol 3.3), or a list of
+ * possible "security types" (protocol 3.7).
+ */
+
+void
+rfbAuthNewClient(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int securityType = rfbSecTypeInvalid;
+
+ if ((!pVNC->rfbAuthPasswdFile && !pVNC->loginAuthEnabled) || cl->reverseConnection) {
+ securityType = rfbSecTypeNone;
+ } else {
+ if (rfbAuthIsBlocked(cl)) {
+ rfbLog("Too many authentication failures - client rejected\n");
+ rfbClientConnFailed(cl, "Too many authentication failures");
+ return;
+ }
+ if (pVNC->rfbAuthPasswdFile)
+ securityType = rfbSecTypeVncAuth;
+ }
+
+ if (cl->protocol_minor_ver < 7) {
+ /* Make sure we use only RFB 3.3 compatible security types. */
+ if (securityType == rfbSecTypeInvalid) {
+ rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n");
+ rfbClientConnFailed(cl, "Your viewer cannot handle required "
+ "authentication methods");
+ return;
+ }
+ rfbSendSecurityType(cl, securityType);
+ } else {
+ /* Here it's ok when securityType is set to rfbSecTypeInvalid. */
+ rfbSendSecurityTypeList(cl, securityType);
+ }
+}
+
+
+/*
+ * Tell the client what security type will be used (protocol 3.3).
+ */
+
+static void
+rfbSendSecurityType(cl, securityType)
+ rfbClientPtr cl;
+ int securityType;
+{
+ CARD32 value32;
+
+ /* Send the value. */
+ value32 = Swap32IfLE(securityType);
+ if (WriteExact(cl->sock, (char *)&value32, 4) < 0) {
+ rfbLogPerror("rfbSendSecurityType: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Decide what to do next. */
+ switch (securityType) {
+ case rfbSecTypeNone:
+ /* Dispatch client input to rfbProcessClientInitMessage. */
+ cl->state = RFB_INITIALISATION;
+ break;
+ case rfbSecTypeVncAuth:
+ /* Begin the standard VNC authentication procedure. */
+ rfbVncAuthSendChallenge(cl);
+ break;
+ default:
+ /* Impossible case (hopefully). */
+ rfbLogPerror("rfbSendSecurityType: assertion failed");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+}
+
+
+/*
+ * Advertise our supported security types (protocol 3.7). The list
+ * will include one standard security type (if primaryType is not set
+ * to rfbSecTypeInvalid), and then one more value telling the client
+ * that we support TightVNC protocol extensions. Thus, currently,
+ * there will be either 1 or 2 items in the list.
+ */
+
+static void
+rfbSendSecurityTypeList(cl, primaryType)
+ rfbClientPtr cl;
+ int primaryType;
+{
+ int count = 1;
+
+ /* Fill in the list of security types in the client structure. */
+ if (primaryType != rfbSecTypeInvalid) {
+ cl->securityTypes[count++] = (CARD8)primaryType;
+ }
+ cl->securityTypes[count] = (CARD8)rfbSecTypeTight;
+ cl->securityTypes[0] = (CARD8)count++;
+
+ /* Send the list. */
+ if (WriteExact(cl->sock, (char *)cl->securityTypes, count) < 0) {
+ rfbLogPerror("rfbSendSecurityTypeList: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Dispatch client input to rfbProcessClientSecurityType. */
+ cl->state = RFB_SECURITY_TYPE;
+}
+
+
+/*
+ * Read the security type chosen by the client (protocol 3.7).
+ */
+
+void
+rfbProcessClientSecurityType(cl)
+ rfbClientPtr cl;
+{
+ int n, count, i;
+ CARD8 chosenType;
+
+ /* Read the security type. */
+ n = ReadExact(cl->sock, (char *)&chosenType, 1);
+ if (n <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientSecurityType: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientSecurityType: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Make sure it was present in the list sent by the server. */
+ count = (int)cl->securityTypes[0];
+ for (i = 1; i <= count; i++) {
+ if (chosenType == cl->securityTypes[i])
+ break;
+ }
+ if (i > count) {
+ rfbLog("rfbProcessClientSecurityType: "
+ "wrong security type requested\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Now go to the proper authentication procedure. */
+ switch (chosenType) {
+ case rfbSecTypeNone:
+ /* Dispatch client input to rfbProcessClientInitMessage. */
+ cl->state = RFB_INITIALISATION;
+ break;
+ case rfbSecTypeVncAuth:
+ /* Begin the standard VNC authentication procedure. */
+ rfbVncAuthSendChallenge(cl);
+ break;
+ case rfbSecTypeTight:
+ /* We are lucky: the viewer supports TightVNC extensions. */
+ rfbLog("Enabling TightVNC protocol extensions\n");
+ /* Switch to the protocol 3.7t. */
+ cl->protocol_tightvnc = TRUE;
+ /* Advertise our tunneling capabilities. */
+ rfbSendTunnelingCaps(cl);
+ break;
+ default:
+ /* Impossible case (hopefully). */
+ rfbLog("rfbProcessClientSecurityType: "
+ "unknown authentication scheme\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+}
+
+
+/*
+ * Send the list of our tunneling capabilities (protocol 3.7t).
+ */
+
+static void
+rfbSendTunnelingCaps(cl)
+ rfbClientPtr cl;
+{
+ rfbTunnelingCapsMsg caps;
+ CARD32 nTypes = 0; /* we don't support tunneling yet */
+
+ caps.nTunnelTypes = Swap32IfLE(nTypes);
+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) {
+ rfbLogPerror("rfbSendTunnelingCaps: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ if (nTypes) {
+ /* Dispatch client input to rfbProcessClientTunnelingType(). */
+ cl->state = RFB_TUNNELING_TYPE;
+ } else {
+ rfbSendAuthCaps(cl);
+ }
+}
+
+
+/*
+ * Read tunneling type requested by the client (protocol 3.7t).
+ * NOTE: Currently, we don't support tunneling, and this function
+ * can never be called.
+ */
+
+void
+rfbProcessClientTunnelingType(cl)
+ rfbClientPtr cl;
+{
+ /* If we were called, then something's really wrong. */
+ rfbLog("rfbProcessClientTunnelingType: not implemented\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+}
+
+
+/*
+ * Send the list of our authentication capabilities to the client
+ * (protocol 3.7t).
+ */
+
+static void
+rfbSendAuthCaps(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ Bool authRequired;
+ rfbAuthenticationCapsMsg caps;
+ rfbCapabilityInfo caplist[MAX_AUTH_CAPS];
+ int count = 0;
+
+ authRequired = ((pVNC->rfbAuthPasswdFile != NULL || pVNC->loginAuthEnabled) &&
+ !cl->reverseConnection);
+
+ if (authRequired) {
+ if (pVNC->loginAuthEnabled) {
+ SetCapInfo(&caplist[count], rfbAuthUnixLogin, rfbTightVncVendor);
+ cl->authCaps[count++] = rfbAuthUnixLogin;
+ }
+ if (pVNC->rfbAuthPasswdFile != NULL) {
+ SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor);
+ cl->authCaps[count++] = rfbAuthVNC;
+ }
+ if (count == 0) {
+ /* Should never happen. */
+ rfbLog("rfbSendAuthCaps: assertion failed\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ }
+
+ cl->nAuthCaps = count;
+ caps.nAuthTypes = Swap32IfLE((CARD32)count);
+ if (WriteExact(cl->sock, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) {
+ rfbLogPerror("rfbSendAuthCaps: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ if (count) {
+ if (WriteExact(cl->sock, (char *)&caplist[0],
+ count * sz_rfbCapabilityInfo) < 0) {
+ rfbLogPerror("rfbSendAuthCaps: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ /* Dispatch client input to rfbProcessClientAuthType. */
+ cl->state = RFB_AUTH_TYPE;
+ } else {
+ /* Dispatch client input to rfbProcessClientInitMessage. */
+ cl->state = RFB_INITIALISATION;
+ }
+}
+
+
+/*
+ * Read client's preferred authentication type (protocol 3.7t).
+ */
+
+void
+rfbProcessClientAuthType(cl)
+ rfbClientPtr cl;
+{
+ CARD32 auth_type;
+ int n, i;
+
+ /* Read authentication type selected by the client. */
+ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type));
+ if (n <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientAuthType: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientAuthType: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ auth_type = Swap32IfLE(auth_type);
+
+ /* Make sure it was present in the list sent by the server. */
+ for (i = 0; i < cl->nAuthCaps; i++) {
+ if (auth_type == cl->authCaps[i])
+ break;
+ }
+ if (i >= cl->nAuthCaps) {
+ rfbLog("rfbProcessClientAuthType: "
+ "wrong authentication type requested\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ switch (auth_type) {
+ case rfbAuthNone:
+ /* Dispatch client input to rfbProcessClientInitMessage. */
+ cl->state = RFB_INITIALISATION;
+ break;
+ case rfbAuthVNC:
+ rfbVncAuthSendChallenge(cl);
+ break;
+ case rfbAuthUnixLogin:
+ /* FIXME: Do (cl->state = RFB_LOGIN_AUTH) instead? */
+ rfbLoginAuthProcessClientMessage(cl);
+ break;
+ default:
+ rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+}
+
+
+/*
+ * Send the authentication challenge.
+ */
+
+static void
+rfbVncAuthSendChallenge(cl)
+ rfbClientPtr cl;
+{
+ vncRandomBytes(cl->authChallenge);
+ if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) {
+ rfbLogPerror("rfbVncAuthSendChallenge: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Dispatch client input to rfbVncAuthProcessResponse. */
+ cl->state = RFB_AUTHENTICATION;
+}
+
+/*
+ * rfbVncAuthProcessResponse is called when the client sends its
+ * authentication response.
+ */
+
+void
+rfbVncAuthProcessResponse(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ char passwdFullControl[9];
+ char passwdViewOnly[9];
+ int numPasswords;
+ Bool ok;
+ int n;
+ CARD8 encryptedChallenge1[CHALLENGESIZE];
+ CARD8 encryptedChallenge2[CHALLENGESIZE];
+ CARD8 response[CHALLENGESIZE];
+ CARD32 authResult;
+
+ n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE);
+ if (n <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbVncAuthProcessResponse: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ numPasswords = vncDecryptPasswdFromFile2(pVNC->rfbAuthPasswdFile,
+ passwdFullControl,
+ passwdViewOnly);
+ if (numPasswords == 0) {
+ rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n",
+ pVNC->rfbAuthPasswdFile);
+
+ authResult = Swap32IfLE(rfbVncAuthFailed);
+
+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
+ rfbLogPerror("rfbVncAuthProcessResponse: write");
+ }
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE);
+ vncEncryptBytes(encryptedChallenge1, passwdFullControl);
+ memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE);
+ vncEncryptBytes(encryptedChallenge2,
+ (numPasswords == 2) ? passwdViewOnly : passwdFullControl);
+
+ /* Lose the passwords from memory */
+ memset(passwdFullControl, 0, 9);
+ memset(passwdViewOnly, 0, 9);
+
+ ok = FALSE;
+ if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) {
+ rfbLog("Full-control authentication passed by %s\n", cl->host);
+ ok = TRUE;
+ cl->viewOnly = FALSE;
+ } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) {
+ rfbLog("View-only authentication passed by %s\n", cl->host);
+ ok = TRUE;
+ cl->viewOnly = TRUE;
+ }
+
+ if (!ok) {
+ rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n",
+ cl->host);
+
+ if (rfbAuthConsiderBlocking(cl)) {
+ authResult = Swap32IfLE(rfbVncAuthTooMany);
+ } else {
+ authResult = Swap32IfLE(rfbVncAuthFailed);
+ }
+
+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
+ rfbLogPerror("rfbVncAuthProcessResponse: write");
+ }
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ rfbAuthUnblock(cl);
+
+ authResult = Swap32IfLE(rfbVncAuthOK);
+
+ if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) {
+ rfbLogPerror("rfbVncAuthProcessResponse: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Dispatch client input to rfbProcessClientInitMessage(). */
+ cl->state = RFB_INITIALISATION;
+}
+
+
+/*
+ * Functions to prevent too many successive authentication failures.
+ * FIXME: This should be performed separately per each client IP.
+ */
+
+/* Maximum authentication failures before blocking connections */
+#define MAX_AUTH_TRIES 5
+
+/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */
+#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000
+
+/*
+ * This function should not be called directly, it is called by
+ * setting a timer in rfbAuthConsiderBlocking().
+ */
+
+static CARD32
+rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ rfbClientPtr cl = (rfbClientPtr) arg;
+ VNCSCREENPTR(cl->pScreen);
+ (void)cl;
+ pVNC->rfbAuthTooManyTries = FALSE;
+ return 0;
+}
+
+/*
+ * This function should be called after each authentication failure.
+ * The return value will be true if there was too many failures.
+ */
+
+Bool
+rfbAuthConsiderBlocking(rfbClientPtr cl)
+{
+ VNCSCREENPTR(cl->pScreen);
+ int i;
+
+ pVNC->rfbAuthTries++;
+
+ if (pVNC->rfbAuthTries >= MAX_AUTH_TRIES) {
+ CARD32 delay = AUTH_TOO_MANY_BASE_DELAY;
+ for (i = MAX_AUTH_TRIES; i < pVNC->rfbAuthTries; i++)
+ delay *= 2;
+ pVNC->timer = TimerSet(pVNC->timer, 0, delay, rfbAuthReenable, cl);
+ pVNC->rfbAuthTooManyTries = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * This function should be called after successful authentication.
+ * It resets the counter of authentication failures. Note that it's
+ * not necessary to clear the rfbAuthTooManyTries flag as it will be
+ * reset by the timer function.
+ */
+
+void
+rfbAuthUnblock(rfbClientPtr cl)
+{
+ VNCSCREENPTR(cl->pScreen);
+ pVNC->rfbAuthTries = 0;
+}
+
+/*
+ * This function should be called before authentication process.
+ * The return value will be true if there was too many authentication
+ * failures, and the server should not allow another try.
+ */
+
+Bool
+rfbAuthIsBlocked(rfbClientPtr cl)
+{
+ VNCSCREENPTR(cl->pScreen);
+ return pVNC->rfbAuthTooManyTries;
+}
+
--- xorg-server-1.7.4/hw/vnc/cmap.c
+++ xorg-server-1.7.4/hw/vnc/cmap.c
@@ -0,0 +1,166 @@
+/*
+ * cmap.c
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1993 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.
+
+*/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "rfb.h"
+
+int
+rfbListInstalledColormaps(pScreen, pmaps)
+ ScreenPtr pScreen;
+ Colormap *pmaps;
+{
+ VNCSCREENPTR(pScreen);
+ /* By the time we are processing requests, we can guarantee that there
+ * is always a colormap installed */
+ if (pVNC->rfbInstalledColormap)
+ *pmaps = pVNC->rfbInstalledColormap->mid;
+
+#if XFREE86VNC
+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps;
+ (*pScreen->ListInstalledColormaps)(pScreen, pmaps);
+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
+#endif
+
+ return (1);
+}
+
+
+void
+rfbInstallColormap(pmap)
+ ColormapPtr pmap;
+{
+ VNCSCREENPTR(pmap->pScreen);
+
+ if (pmap != pVNC->rfbInstalledColormap) {
+
+ if(pVNC->rfbInstalledColormap != (ColormapPtr)None)
+ WalkTree(pmap->pScreen, TellLostMap,
+ (char *)&pVNC->rfbInstalledColormap->mid);
+ /* Install pmap */
+ pVNC->rfbInstalledColormap = pmap;
+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
+
+ rfbSetClientColourMaps(0, 0);
+ }
+#if XFREE86VNC
+ pmap->pScreen->InstallColormap = pVNC->InstallColormap;
+ (*pmap->pScreen->InstallColormap)(pmap);
+ pmap->pScreen->InstallColormap = rfbInstallColormap;
+#endif
+}
+
+void
+rfbUninstallColormap(pmap)
+ ColormapPtr pmap;
+{
+ VNCSCREENPTR(pmap->pScreen);
+
+ if(pmap == pVNC->rfbInstalledColormap)
+ {
+ if (pmap->mid != pmap->pScreen->defColormap)
+ {
+ pVNC->rfbInstalledColormap =
+ (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
+ RT_COLORMAP);
+ (*pmap->pScreen->InstallColormap)(pVNC->rfbInstalledColormap);
+ }
+ }
+#if XFREE86VNC
+ pmap->pScreen->UninstallColormap = pVNC->UninstallColormap;
+ (*pmap->pScreen->UninstallColormap)(pmap);
+ pmap->pScreen->UninstallColormap = rfbUninstallColormap;
+#endif
+}
+
+
+/*
+ * rfbStoreColors. We have a set of pixels but they may be in any order.
+ * If some of them happen to be in continuous ascending order then we can
+ * group them together into a single call to rfbSetClientColourMaps.
+ */
+
+void
+rfbStoreColors(pmap, ndef, pdefs)
+ ColormapPtr pmap;
+ int ndef;
+ xColorItem *pdefs;
+{
+ VNCSCREENPTR(pmap->pScreen);
+ int i;
+ int first = -1;
+ int n = 0;
+
+ if (pmap == pVNC->rfbInstalledColormap) {
+ for (i = 0; i < ndef; i++) {
+ if ((first != -1) && (first + n == pdefs[i].pixel)) {
+ n++;
+ } else {
+ if (first != -1) {
+ rfbSetClientColourMaps(first, n);
+ }
+ first = pdefs[i].pixel;
+ n = 1;
+ }
+ }
+ rfbSetClientColourMaps(first, n);
+ }
+#if XFREE86VNC
+ pmap->pScreen->StoreColors = pVNC->StoreColors;
+ (*pmap->pScreen->StoreColors)(pmap, ndef, pdefs);
+ pmap->pScreen->StoreColors = rfbStoreColors;
+#endif
+}
--- xorg-server-1.7.4/hw/vnc/corre.c
+++ xorg-server-1.7.4/hw/vnc/corre.c
@@ -0,0 +1,353 @@
+/*
+ * corre.c
+ *
+ * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This
+ * code is based on krw's original javatel rfbserver.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include "rfb.h"
+
+/*
+ * rreBeforeBuf contains pixel data in the client's format.
+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
+ * larger than the raw data or if it exceeds rreAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int rreBeforeBufSize = 0;
+static unsigned char *rreBeforeBuf = NULL;
+
+static int rreAfterBufSize = 0;
+static unsigned char *rreAfterBuf = NULL;
+static int rreAfterBufLen;
+
+static int subrectEncode8(CARD8 *data, int w, int h);
+static int subrectEncode16(CARD16 *data, int w, int h);
+static int subrectEncode32(CARD32 *data, int w, int h);
+static CARD32 getBgColour(char *data, int size, int bpp);
+static Bool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y,
+ int w, int h);
+
+
+/*
+ * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE
+ * encoding.
+ */
+
+Bool
+rfbSendRectEncodingCoRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ if (h > cl->correMaxHeight) {
+ return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) &&
+ rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight,
+ w, h - cl->correMaxHeight));
+ }
+
+ if (w > cl->correMaxWidth) {
+ return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) &&
+ rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y,
+ w - cl->correMaxWidth, h));
+ }
+
+ return rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h);
+}
+
+
+
+/*
+ * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256)
+ * rectangle using CoRRE encoding.
+ */
+
+static Bool
+rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+ rfbRREHeader hdr;
+ int nSubrects;
+ int i;
+ int maxRawSize = (pVNC->width * pVNC->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (rreBeforeBufSize < maxRawSize) {
+ rreBeforeBufSize = maxRawSize;
+ if (rreBeforeBuf == NULL)
+ rreBeforeBuf = (unsigned char *)xalloc(rreBeforeBufSize);
+ else
+ rreBeforeBuf = (unsigned char *)xrealloc(rreBeforeBuf, rreBeforeBufSize);
+ }
+
+ if (rreAfterBufSize < maxRawSize) {
+ rreAfterBufSize = maxRawSize;
+ if (rreAfterBuf == NULL)
+ rreAfterBuf = (unsigned char *)xalloc(rreAfterBufSize);
+ else
+ rreAfterBuf = (unsigned char *)xrealloc(rreAfterBuf, rreAfterBufSize);
+ }
+
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable,
+ &pVNC->rfbServerFormat,
+ &cl->format, rreBeforeBuf,
+ pVNC->paddedWidthInBytes, w, h, x, y);
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
+ break;
+ case 16:
+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
+ break;
+ case 32:
+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
+ break;
+ default:
+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
+ exit(1);
+ }
+
+ if (nSubrects < 0) {
+
+ /* RRE encoding was too large, use raw */
+
+ return rfbSendRectEncodingRaw(cl, x, y, w, h);
+ }
+
+ cl->rfbRectanglesSent[rfbEncodingCoRRE]++;
+ cl->rfbBytesSent[rfbEncodingCoRRE] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbRREHeader + rreAfterBufLen);
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingCoRRE);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nSubrects = Swap32IfLE(nSubrects);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader);
+ pVNC->ublen += sz_rfbRREHeader;
+
+ for (i = 0; i < rreAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen;
+
+ if (i + bytesToCopy > rreAfterBufLen) {
+ bytesToCopy = rreAfterBufLen - i;
+ }
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy);
+
+ pVNC->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (pVNC->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * subrectEncode() encodes the given multicoloured rectangle as a background
+ * colour overwritten by single-coloured rectangles. It returns the number
+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
+ * single-colour rectangle partition is not optimal, but does find the biggest
+ * horizontal or vertical rectangle top-left anchored to each consecutive
+ * coordinate position.
+ *
+ * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
+ * <subrect> is [<colour><x><y><w><h>].
+ */
+
+#define DEFINE_SUBRECT_ENCODE(bpp) \
+static int \
+subrectEncode##bpp(data,w,h) \
+ CARD##bpp *data; \
+ int w; \
+ int h; \
+{ \
+ CARD##bpp cl; \
+ rfbCoRRERectangle subrect; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
+ \
+ *((CARD##bpp*)rreAfterBuf) = bg; \
+ \
+ rreAfterBufLen = (bpp/8); \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl) {break;} \
+ i = x; \
+ while ((seg[i] == cl) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
+ * We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ subrect.x = thex; \
+ subrect.y = they; \
+ subrect.w = thew; \
+ subrect.h = theh; \
+ \
+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \
+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
+ return -1; \
+ \
+ numsubs += 1; \
+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
+ rreAfterBufLen += (bpp/8); \
+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \
+ rreAfterBufLen += sz_rfbCoRRERectangle; \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ return numsubs; \
+}
+
+DEFINE_SUBRECT_ENCODE(8)
+DEFINE_SUBRECT_ENCODE(16)
+DEFINE_SUBRECT_ENCODE(32)
+
+
+/*
+ * getBgColour() gets the most prevalent colour in a byte array.
+ */
+static CARD32
+getBgColour(data,size,bpp)
+ char *data;
+ int size;
+ int bpp;
+{
+
+#define NUMCLRS 256
+
+ static int counts[NUMCLRS];
+ int i,j,k;
+
+ int maxcount = 0;
+ CARD8 maxclr = 0;
+
+ if (bpp != 8) {
+ if (bpp == 16) {
+ return ((CARD16 *)data)[0];
+ } else if (bpp == 32) {
+ return ((CARD32 *)data)[0];
+ } else {
+ rfbLog("getBgColour: bpp %d?\n",bpp);
+ exit(1);
+ }
+ }
+
+ for (i=0; i<NUMCLRS; i++) {
+ counts[i] = 0;
+ }
+
+ for (j=0; j<size; j++) {
+ k = (int)(((CARD8 *)data)[j]);
+ if (k >= NUMCLRS) {
+ rfbLog("getBgColour: unusual colour = %d\n", k);
+ exit(1);
+ }
+ counts[k] += 1;
+ if (counts[k] > maxcount) {
+ maxcount = counts[k];
+ maxclr = ((CARD8 *)data)[j];
+ }
+ }
+
+ return maxclr;
+}
--- xorg-server-1.7.4/hw/vnc/cursor.c
+++ xorg-server-1.7.4/hw/vnc/cursor.c
@@ -0,0 +1,407 @@
+/*
+ * cursor.c - support for cursor shape updates.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include "rfb.h"
+#include "mipointer.h"
+#include "sprite.h"
+#include "cursorstr.h"
+#include "servermd.h"
+
+
+/* Copied from Xvnc/lib/font/util/utilbitmap.c */
+static 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
+};
+
+
+static int EncodeRichCursorData8 (unsigned char *buf, rfbPixelFormat *fmt,
+ CursorPtr pCursor);
+static int EncodeRichCursorData16 (ScreenPtr pScreen,
+ unsigned char *buf, rfbPixelFormat *fmt,
+ CursorPtr pCursor);
+static int EncodeRichCursorData32 (ScreenPtr pScreen,
+ unsigned char *buf, rfbPixelFormat *fmt,
+ CursorPtr pCursor);
+
+
+/*
+ * Send cursor shape either in X-style format or in client pixel format.
+ */
+
+Bool
+rfbSendCursorShape(cl, pScreen)
+ rfbClientPtr cl;
+ ScreenPtr pScreen;
+{
+ VNCSCREENPTR(pScreen);
+ CursorPtr pCursor;
+ rfbFramebufferUpdateRectHeader rect;
+ rfbXCursorColors colors;
+ int saved_ublen;
+ int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes;
+ int i, j;
+ CARD8 *bitmapData;
+ CARD8 bitmapByte;
+
+ if (cl->useRichCursorEncoding) {
+ rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
+ } else {
+ rect.encoding = Swap32IfLE(rfbEncodingXCursor);
+ }
+
+#if XFREE86VNC
+ pCursor = pVNC->pCurs;
+#else
+ pCursor = rfbSpriteGetCursorPtr(pScreen);
+#endif
+
+ /* If there is no cursor, send update with empty cursor data. */
+
+ if ( pCursor != NULL &&
+ pCursor->bits->width == 1 &&
+ pCursor->bits->height == 1 &&
+ pCursor->bits->mask[0] == 0 ) {
+ pCursor = NULL;
+ }
+
+ if (pCursor == NULL) {
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ rect.r.x = rect.r.y = 0;
+ rect.r.w = rect.r.h = 0;
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbCursorShapeBytesSent += sz_rfbFramebufferUpdateRectHeader;
+ cl->rfbCursorShapeUpdatesSent++;
+
+ return TRUE;
+ }
+
+ /* Calculate data sizes. */
+
+ bitmapRowBytes = (pCursor->bits->width + 7) / 8;
+ paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1);
+ maskBytes = bitmapRowBytes * pCursor->bits->height;
+ dataBytes = (cl->useRichCursorEncoding) ?
+ (pCursor->bits->width * pCursor->bits->height *
+ (cl->format.bitsPerPixel / 8)) : maskBytes;
+
+ /* Send buffer contents if needed. */
+
+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader +
+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if ( pVNC->ublen + sz_rfbFramebufferUpdateRectHeader +
+ sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
+ return FALSE; /* FIXME. */
+ }
+
+ saved_ublen = pVNC->ublen;
+
+ /* Prepare rectangle header. */
+
+ rect.r.x = Swap16IfLE(pCursor->bits->xhot);
+ rect.r.y = Swap16IfLE(pCursor->bits->yhot);
+ rect.r.w = Swap16IfLE(pCursor->bits->width);
+ rect.r.h = Swap16IfLE(pCursor->bits->height);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ /* Prepare actual cursor data (depends on encoding used). */
+
+ if (!cl->useRichCursorEncoding) {
+ /* XCursor encoding. */
+ colors.foreRed = (char)(pCursor->foreRed >> 8);
+ colors.foreGreen = (char)(pCursor->foreGreen >> 8);
+ colors.foreBlue = (char)(pCursor->foreBlue >> 8);
+ colors.backRed = (char)(pCursor->backRed >> 8);
+ colors.backGreen = (char)(pCursor->backGreen >> 8);
+ colors.backBlue = (char)(pCursor->backBlue >> 8);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&colors, sz_rfbXCursorColors);
+ pVNC->ublen += sz_rfbXCursorColors;
+
+ bitmapData = (CARD8 *)pCursor->bits->source;
+
+ for (i = 0; i < pCursor->bits->height; i++) {
+ for (j = 0; j < bitmapRowBytes; j++) {
+ bitmapByte = bitmapData[i * paddedRowBytes + j];
+ if (screenInfo.bitmapBitOrder == LSBFirst) {
+ bitmapByte = _reverse_byte[bitmapByte];
+ }
+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte;
+ }
+ }
+ } else {
+ /* RichCursor encoding. */
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ pVNC->ublen += EncodeRichCursorData8(&pVNC->updateBuf[pVNC->ublen],
+ &cl->format, pCursor);
+ break;
+ case 16:
+ pVNC->ublen += EncodeRichCursorData16(pScreen, &pVNC->updateBuf[pVNC->ublen],
+ &cl->format, pCursor);
+ break;
+ case 32:
+ pVNC->ublen += EncodeRichCursorData32(pScreen, &pVNC->updateBuf[pVNC->ublen],
+ &cl->format, pCursor);
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ /* Prepare transparency mask. */
+
+ bitmapData = (CARD8 *)pCursor->bits->mask;
+
+ for (i = 0; i < pCursor->bits->height; i++) {
+ for (j = 0; j < bitmapRowBytes; j++) {
+ bitmapByte = bitmapData[i * paddedRowBytes + j];
+ if (screenInfo.bitmapBitOrder == LSBFirst) {
+ bitmapByte = _reverse_byte[bitmapByte];
+ }
+ pVNC->updateBuf[pVNC->ublen++] = (char)bitmapByte;
+ }
+ }
+
+ /* Update statistics. */
+
+ cl->rfbCursorShapeBytesSent += (pVNC->ublen - saved_ublen);
+ cl->rfbCursorShapeUpdatesSent++;
+
+ return TRUE;
+}
+
+/*
+ * Send cursor position (PointerPos pseudo-encoding).
+ */
+Bool
+rfbSendCursorPos(cl, pScreen)
+ rfbClientPtr cl;
+ ScreenPtr pScreen;
+{
+ VNCSCREENPTR(pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+#if XFREE86VNC
+ ScreenPtr pCursorScreen = miPointerCurrentScreen(); /*XXX deprecated*/
+#endif
+ int x, y;
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+#if XFREE86VNC
+ if (pScreen == pCursorScreen)
+ miPointerPosition(&x, &y);
+#else
+ rfbSpriteGetCursorPos(pScreen, &x, &y);
+#endif
+
+ rect.encoding = Swap32IfLE(rfbEncodingPointerPos);
+ rect.r.x = Swap16IfLE((CARD16)x);
+ rect.r.y = Swap16IfLE((CARD16)y);
+ rect.r.w = 0;
+ rect.r.h = 0;
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbCursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader;
+ cl->rfbCursorPosUpdatesSent++;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ cl->cursorX = x;
+ cl->cursorY = y;
+
+ return TRUE;
+}
+
+/*
+ * Code to convert cursor source bitmap to the desired pixel format.
+ */
+
+#define RGB48_TO_PIXEL(fmt,r,g,b) \
+ (((CARD32)(r) * ((fmt)->redMax + 1) >> 16) << (fmt)->redShift | \
+ ((CARD32)(g) * ((fmt)->greenMax + 1) >> 16) << (fmt)->greenShift | \
+ ((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift)
+
+static int
+EncodeRichCursorData8(buf, fmt, pCursor)
+ unsigned char *buf;
+ rfbPixelFormat *fmt;
+ CursorPtr pCursor;
+{
+ int widthPixels, widthBytes;
+ int x, y, b;
+ CARD8 *src;
+ char pix[2];
+ CARD8 bitmapByte;
+
+ pix[0] = (char)RGB48_TO_PIXEL(fmt, pCursor->backRed, pCursor->backGreen,
+ pCursor->backBlue);
+ pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen,
+ pCursor->foreBlue);
+
+ src = (CARD8 *)pCursor->bits->source;
+ widthPixels = pCursor->bits->width;
+ widthBytes = PixmapBytePad(widthPixels, 1);
+
+ for (y = 0; y < pCursor->bits->height; y++) {
+ for (x = 0; x < widthPixels / 8; x++) {
+ bitmapByte = src[y * widthBytes + x];
+ if (screenInfo.bitmapBitOrder == LSBFirst) {
+ bitmapByte = _reverse_byte[bitmapByte];
+ }
+ for (b = 7; b >= 0; b--) {
+ *buf++ = pix[bitmapByte >> b & 1];
+ }
+ }
+ if (widthPixels % 8) {
+ bitmapByte = src[y * widthBytes + x];
+ if (screenInfo.bitmapBitOrder == LSBFirst) {
+ bitmapByte = _reverse_byte[bitmapByte];
+ }
+ for (b = 7; b > 7 - widthPixels % 8; b--) {
+ *buf++ = pix[bitmapByte >> b & 1];
+ }
+ }
+ }
+
+ return (widthPixels * pCursor->bits->height);
+}
+
+#define DEFINE_RICH_ENCODE(bpp) \
+ \
+static int \
+EncodeRichCursorData##bpp(pScreen, buf, fmt, pCursor) \
+ ScreenPtr pScreen; \
+ unsigned char *buf; \
+ rfbPixelFormat *fmt; \
+ CursorPtr pCursor; \
+{ \
+ VNCSCREENPTR(pScreen); \
+ int widthPixels, widthBytes; \
+ int x, y, b; \
+ CARD8 *src; \
+ CARD##bpp pix[2]; \
+ CARD8 bitmapByte; \
+ \
+ pix[0] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->backRed, \
+ pCursor->backGreen, \
+ pCursor->backBlue); \
+ pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \
+ pCursor->foreGreen, \
+ pCursor->foreBlue); \
+ if (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian) { \
+ pix[0] = Swap##bpp(pix[0]); \
+ pix[1] = Swap##bpp(pix[1]); \
+ } \
+ \
+ src = (CARD8 *)pCursor->bits->source; \
+ widthPixels = pCursor->bits->width; \
+ widthBytes = PixmapBytePad(widthPixels, 1); \
+ \
+ for (y = 0; y < pCursor->bits->height; y++) { \
+ for (x = 0; x < widthPixels / 8; x++) { \
+ bitmapByte = src[y * widthBytes + x]; \
+ if (screenInfo.bitmapBitOrder == LSBFirst) { \
+ bitmapByte = _reverse_byte[bitmapByte]; \
+ } \
+ for (b = 7; b >= 0; b--) { \
+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \
+ sizeof(CARD##bpp)); \
+ buf += sizeof(CARD##bpp); \
+ } \
+ } \
+ if (widthPixels % 8) { \
+ bitmapByte = src[y * widthBytes + x]; \
+ if (screenInfo.bitmapBitOrder == LSBFirst) { \
+ bitmapByte = _reverse_byte[bitmapByte]; \
+ } \
+ for (b = 7; b > 7 - widthPixels % 8; b--) { \
+ memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \
+ sizeof(CARD##bpp)); \
+ buf += sizeof(CARD##bpp); \
+ } \
+ } \
+ } \
+ \
+ return (widthPixels * pCursor->bits->height * (bpp / 8)); \
+}
+
+DEFINE_RICH_ENCODE(16)
+DEFINE_RICH_ENCODE(32)
+
--- xorg-server-1.7.4/hw/vnc/cutpaste.c
+++ xorg-server-1.7.4/hw/vnc/cutpaste.c
@@ -0,0 +1,87 @@
+/*
+ * cutpaste.c - routines to deal with cut & paste buffers / selection.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "rfb.h"
+#include "selection.h"
+#include "input.h"
+#include <X11/Xatom.h>
+
+extern Selection *CurrentSelections;
+extern int NumCurrentSelections;
+
+
+static Bool inSetXCutText = FALSE;
+
+/*
+ * rfbSetXCutText sets the cut buffer to be the given string. We also clear
+ * the primary selection. Ideally we'd like to set it to the same thing, but I
+ * can't work out how to do that without some kind of helper X client.
+ */
+
+void
+rfbSetXCutText(char *str, int len)
+{
+ int i = 0;
+ Selection *pSel;
+
+ inSetXCutText = TRUE;
+ ChangeWindowProperty(WindowTable[0], XA_CUT_BUFFER0, XA_STRING,
+ 8, PropModeReplace, len,
+ (pointer)str, TRUE);
+
+ if (dixLookupSelection(&pSel, XA_PRIMARY, serverClient, DixSetAttrAccess)) {
+ xEvent event;
+
+ if (pSel->client) {
+ event.u.u.type = SelectionClear;
+ event.u.selectionClear.time = GetTimeInMillis();
+ event.u.selectionClear.window = pSel->window;
+ event.u.selectionClear.atom = pSel->selection;
+ (void) TryClientEvents (pSel->client, &event, 1,
+ NoEventMask, NoEventMask /* CantBeFiltered */,
+ NullGrab);
+ }
+
+ pSel->window = None;
+ pSel->pWin = NULL;
+ pSel->client = NullClient;
+ }
+
+ inSetXCutText = FALSE;
+}
+
+
+void rfbGotXCutText(char *str, int len)
+{
+ if (!inSetXCutText)
+ rfbSendServerCutText(str, len);
+}
--- xorg-server-1.7.4/hw/vnc/d3des.c
+++ xorg-server-1.7.4/hw/vnc/d3des.c
@@ -0,0 +1,437 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC. Also the bytebit[] array
+ * has been reversed so that the most significant bit in each byte of the
+ * key is ignored, not the least significant.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* D3DES (V5.09) -
+ *
+ * A portable, public domain, version of the Data Encryption Standard.
+ *
+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
+ * for humouring me on.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "d3des.h"
+
+static void scrunch(unsigned char *, unsigned long *);
+static void unscrun(unsigned long *, unsigned char *);
+static void desfunc(unsigned long *, unsigned long *);
+static void cookey(unsigned long *);
+
+static unsigned long KnL[32] = { 0L };
+
+static unsigned short bytebit[8] = {
+ 01, 02, 04, 010, 020, 040, 0100, 0200 };
+
+static unsigned long bigbyte[24] = {
+ 0x800000L, 0x400000L, 0x200000L, 0x100000L,
+ 0x80000L, 0x40000L, 0x20000L, 0x10000L,
+ 0x8000L, 0x4000L, 0x2000L, 0x1000L,
+ 0x800L, 0x400L, 0x200L, 0x100L,
+ 0x80L, 0x40L, 0x20L, 0x10L,
+ 0x8L, 0x4L, 0x2L, 0x1L };
+
+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
+
+static unsigned char pc1[56] = {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
+
+static unsigned char totrot[16] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
+
+static unsigned char pc2[48] = {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
+
+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
+unsigned char *key;
+int edf;
+{
+ register int i, j, l, m, n;
+ unsigned char pc1m[56], pcr[56];
+ unsigned long kn[32];
+
+ for ( j = 0; j < 56; j++ ) {
+ l = pc1[j];
+ m = l & 07;
+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
+ }
+ for( i = 0; i < 16; i++ ) {
+ if( edf == DE1 ) m = (15 - i) << 1;
+ else m = i << 1;
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for( j = 0; j < 28; j++ ) {
+ l = j + totrot[i];
+ if( l < 28 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 28; j < 56; j++ ) {
+ l = j + totrot[i];
+ if( l < 56 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 0; j < 24; j++ ) {
+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
+ }
+ }
+ cookey(kn);
+ return;
+ }
+
+static void cookey(raw1)
+register unsigned long *raw1;
+{
+ register unsigned long *cook, *raw0;
+ unsigned long dough[32];
+ register int i;
+
+ cook = dough;
+ for( i = 0; i < 16; i++, raw1++ ) {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+ usekey(dough);
+ return;
+ }
+
+void cpkey(into)
+register unsigned long *into;
+{
+ register unsigned long *from, *endp;
+
+ from = KnL, endp = &KnL[32];
+ while( from < endp ) *into++ = *from++;
+ return;
+ }
+
+void usekey(from)
+register unsigned long *from;
+{
+ register unsigned long *to, *endp;
+
+ to = KnL, endp = &KnL[32];
+ while( to < endp ) *to++ = *from++;
+ return;
+ }
+
+void des(inblock, outblock)
+unsigned char *inblock, *outblock;
+{
+ unsigned long work[2];
+
+ scrunch(inblock, work);
+ desfunc(work, KnL);
+ unscrun(work, outblock);
+ return;
+ }
+
+static void scrunch(outof, into)
+register unsigned char *outof;
+register unsigned long *into;
+{
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into++ |= (*outof++ & 0xffL);
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into |= (*outof & 0xffL);
+ return;
+ }
+
+static void unscrun(outof, into)
+register unsigned long *outof;
+register unsigned char *into;
+{
+ *into++ = (*outof >> 24) & 0xffL;
+ *into++ = (*outof >> 16) & 0xffL;
+ *into++ = (*outof >> 8) & 0xffL;
+ *into++ = *outof++ & 0xffL;
+ *into++ = (*outof >> 24) & 0xffL;
+ *into++ = (*outof >> 16) & 0xffL;
+ *into++ = (*outof >> 8) & 0xffL;
+ *into = *outof & 0xffL;
+ return;
+ }
+
+static unsigned long SP1[64] = {
+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
+
+static unsigned long SP2[64] = {
+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
+
+static unsigned long SP3[64] = {
+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
+
+static unsigned long SP4[64] = {
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
+
+static unsigned long SP5[64] = {
+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
+
+static unsigned long SP6[64] = {
+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
+
+static unsigned long SP7[64] = {
+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
+
+static unsigned long SP8[64] = {
+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
+
+static void desfunc(block, keys)
+register unsigned long *block, *keys;
+{
+ register unsigned long fval, work, right, leftt;
+ register int round;
+
+ leftt = block[0];
+ right = block[1];
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
+
+ for( round = 0; round < 8; round++ ) {
+ work = (right << 28) | (right >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ leftt ^= fval;
+ work = (leftt << 28) | (leftt >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = (leftt << 31) | (leftt >> 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+ *block++ = right;
+ *block = leftt;
+ return;
+ }
+
+/* Validation sets:
+ *
+ * Single-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : c957 4425 6a5e d31d
+ *
+ * Double-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : 7f1d 0a77 826b 8aff
+ *
+ * Double-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
+ *
+ * Triple-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : de0b 7c06 ae5e 0ed5
+ *
+ * Triple-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
+ *
+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
+ **********************************************************************/
--- xorg-server-1.7.4/hw/vnc/d3des.h
+++ xorg-server-1.7.4/hw/vnc/d3des.h
@@ -0,0 +1,51 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* d3des.h -
+ *
+ * Headers and defines for d3des.c
+ * Graven Imagery, 1992.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
+ * (GEnie : OUTER; CIS : [71755,204])
+ */
+
+#define EN0 0 /* MODE == encrypt */
+#define DE1 1 /* MODE == decrypt */
+
+extern void deskey(unsigned char *, int);
+/* hexkey[8] MODE
+ * Sets the internal key register according to the hexadecimal
+ * key contained in the 8 bytes of hexkey, according to the DES,
+ * for encryption or decryption according to MODE.
+ */
+
+extern void usekey(unsigned long *);
+/* cookedkey[32]
+ * Loads the internal key register with the data in cookedkey.
+ */
+
+extern void cpkey(unsigned long *);
+/* cookedkey[32]
+ * Copies the contents of the internal key register into the storage
+ * located at &cookedkey[0].
+ */
+
+extern void des(unsigned char *, unsigned char *);
+/* from[8] to[8]
+ * Encrypts/Decrypts (according to the key currently loaded in the
+ * internal key register) one block of eight bytes at address 'from'
+ * into the block at address 'to'. They can be the same.
+ */
+
+/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
+ ********************************************************************/
--- xorg-server-1.7.4/hw/vnc/dispcur.c
+++ xorg-server-1.7.4/hw/vnc/dispcur.c
@@ -0,0 +1,792 @@
+/*
+ * dispcur.c
+ *
+ * cursor display routines - based on midispcur.c
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1989 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.
+*/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#define NEED_EVENTS
+# include <X11/X.h>
+# include "rfb.h"
+# include "misc.h"
+# include "input.h"
+# include "cursorstr.h"
+# include "windowstr.h"
+# include "regionstr.h"
+# include "dixstruct.h"
+# include "scrnintstr.h"
+# include "servermd.h"
+# include "sprite.h"
+# include "gcstruct.h"
+
+#ifdef ARGB_CURSOR
+# include "picturestr.h"
+#endif
+
+/* per-screen private data */
+
+static DevPrivateKey rfbDCScreenKey = &rfbDCScreenKey;
+
+static Bool rfbDCCloseScreen(int index, ScreenPtr pScreen);
+
+typedef struct {
+ GCPtr pSourceGC, pMaskGC;
+ GCPtr pSaveGC, pRestoreGC;
+ GCPtr pMoveGC;
+ GCPtr pPixSourceGC, pPixMaskGC;
+ CloseScreenProcPtr CloseScreen;
+ PixmapPtr pSave, pTemp;
+#ifdef ARGB_CURSOR
+ PicturePtr pRootPicture;
+ PicturePtr pTempPicture;
+#endif
+} rfbDCScreenRec, *rfbDCScreenPtr;
+
+/* per-cursor per-screen private data */
+typedef struct {
+ PixmapPtr sourceBits; /* source bits */
+ PixmapPtr maskBits; /* mask bits */
+#ifdef ARGB_CURSOR
+ PicturePtr pPicture;
+#endif
+} rfbDCCursorRec, *rfbDCCursorPtr;
+
+/*
+ * sprite/cursor method table
+ */
+
+static Bool rfbDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+static Bool rfbDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
+static Bool rfbDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ int x, int y, unsigned long source,
+ unsigned long mask);
+static Bool rfbDCSaveUnderCursor(ScreenPtr pScreen, int x, int y,
+ int w, int h);
+static Bool rfbDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y,
+ int w, int h);
+static Bool rfbDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor,
+ int x, int y, int w, int h, int dx, int dy,
+ unsigned long source, unsigned long mask);
+static Bool rfbDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h,
+ int dx, int dy);
+
+static rfbSpriteCursorFuncRec rfbDCFuncs = {
+ rfbDCRealizeCursor,
+ rfbDCUnrealizeCursor,
+ rfbDCPutUpCursor,
+ rfbDCSaveUnderCursor,
+ rfbDCRestoreUnderCursor,
+ rfbDCMoveCursor,
+ rfbDCChangeSave,
+};
+
+Bool
+rfbDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs)
+{
+ rfbDCScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbDCScreenPtr) xalloc (sizeof (rfbDCScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+
+ /*
+ * initialize the entire private structure to zeros
+ */
+
+ pScreenPriv->pSourceGC =
+ pScreenPriv->pMaskGC =
+ pScreenPriv->pSaveGC =
+ pScreenPriv->pRestoreGC =
+ pScreenPriv->pMoveGC =
+ pScreenPriv->pPixSourceGC =
+ pScreenPriv->pPixMaskGC = NULL;
+#ifdef ARGB_CURSOR
+ pScreenPriv->pRootPicture = NULL;
+ pScreenPriv->pTempPicture = NULL;
+#endif
+
+ pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = rfbDCCloseScreen;
+
+ dixSetPrivate(&pScreen->devPrivates, rfbDCScreenKey, pScreenPriv);
+
+ if (!rfbSpriteInitialize (pScreen, &rfbDCFuncs, screenFuncs))
+ {
+ xfree ((pointer) pScreenPriv);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0)
+#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE)
+#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0)
+
+static Bool
+rfbDCCloseScreen (index, pScreen)
+ ScreenPtr pScreen;
+{
+ rfbDCScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ tossGC (pScreenPriv->pSourceGC);
+ tossGC (pScreenPriv->pMaskGC);
+ tossGC (pScreenPriv->pSaveGC);
+ tossGC (pScreenPriv->pRestoreGC);
+ tossGC (pScreenPriv->pMoveGC);
+ tossGC (pScreenPriv->pPixSourceGC);
+ tossGC (pScreenPriv->pPixMaskGC);
+ tossPix (pScreenPriv->pSave);
+ tossPix (pScreenPriv->pTemp);
+#ifdef ARGB_CURSOR
+ tossPict (pScreenPriv->pRootPicture);
+ tossPict (pScreenPriv->pTempPicture);
+#endif
+ xfree ((pointer) pScreenPriv);
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+static Bool
+rfbDCRealizeCursor (pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ if (pCursor->bits->refcnt <= 1)
+ dixSetPrivate(&pCursor->bits->devPrivates, pScreen, NULL);
+ return TRUE;
+}
+
+#ifdef ARGB_CURSOR
+#define EnsurePicture(picture,draw,win) (picture || rfbDCMakePicture(&picture,draw,win))
+
+static VisualPtr
+rfbDCGetWindowVisual (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ VisualID vid = wVisual (pWin);
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ if (pScreen->visuals[i].vid == vid)
+ return &pScreen->visuals[i];
+ return 0;
+}
+
+static PicturePtr
+rfbDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
+{
+ ScreenPtr pScreen = pDraw->pScreen;
+ VisualPtr pVisual;
+ PictFormatPtr pFormat;
+ XID subwindow_mode = IncludeInferiors;
+ PicturePtr pPicture;
+ int error;
+
+ pVisual = rfbDCGetWindowVisual (pWin);
+ if (!pVisual)
+ return 0;
+ pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
+ if (!pFormat)
+ return 0;
+ pPicture = CreatePicture (0, pDraw, pFormat,
+ CPSubwindowMode, &subwindow_mode,
+ serverClient, &error);
+ *ppPicture = pPicture;
+ return pPicture;
+}
+#endif
+
+static rfbDCCursorPtr
+rfbDCRealize (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ rfbDCCursorPtr pPriv;
+ GCPtr pGC;
+ XID gcvals[3];
+
+ pPriv = (rfbDCCursorPtr) xalloc (sizeof (rfbDCCursorRec));
+ if (!pPriv)
+ return (rfbDCCursorPtr)NULL;
+#ifdef ARGB_CURSOR
+ if (pCursor->bits->argb)
+ {
+ PixmapPtr pPixmap;
+ PictFormatPtr pFormat;
+ int error;
+
+ pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
+ if (!pFormat)
+ {
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+
+ pPriv->sourceBits = 0;
+ pPriv->maskBits = 0;
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
+ pCursor->bits->height, 32, 0);
+ if (!pPixmap)
+ {
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+ pGC = GetScratchGC (32, pScreen);
+ if (!pGC)
+ {
+ (*pScreen->DestroyPixmap) (pPixmap);
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+ ValidateGC (&pPixmap->drawable, pGC);
+ (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
+ 0, 0, pCursor->bits->width,
+ pCursor->bits->height,
+ 0, ZPixmap, (char *) pCursor->bits->argb);
+ FreeScratchGC (pGC);
+ pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
+ pFormat, 0, 0, serverClient, &error);
+ (*pScreen->DestroyPixmap) (pPixmap);
+ if (!pPriv->pPicture)
+ {
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+ dixSetPrivate(&pCursor->bits->devPrivates, pScreen, pPriv);
+ return pPriv;
+ }
+ pPriv->pPicture = 0;
+#endif
+ pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->sourceBits)
+ {
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+ pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
+ if (!pPriv->maskBits)
+ {
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ xfree ((pointer) pPriv);
+ return (rfbDCCursorPtr)NULL;
+ }
+ dixSetPrivate(&pCursor->bits->devPrivates, pScreen, pPriv);
+
+ /* create the two sets of bits, clipping as appropriate */
+
+ pGC = GetScratchGC (1, pScreen);
+ if (!pGC)
+ {
+ (void) rfbDCUnrealizeCursor (pScreen, pCursor);
+ return (rfbDCCursorPtr)NULL;
+ }
+
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ gcvals[0] = GXand;
+ ChangeGC (pGC, GCFunction, gcvals);
+ ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+
+ /* mask bits -- pCursor->mask & ~pCursor->source */
+ gcvals[0] = GXcopy;
+ ChangeGC (pGC, GCFunction, gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->mask);
+ gcvals[0] = GXandInverted;
+ ChangeGC (pGC, GCFunction, gcvals);
+ ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
+ (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
+ 0, 0, pCursor->bits->width, pCursor->bits->height,
+ 0, XYPixmap, (char *)pCursor->bits->source);
+ FreeScratchGC (pGC);
+ return pPriv;
+}
+
+static Bool
+rfbDCUnrealizeCursor (pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ rfbDCCursorPtr pPriv;
+
+ pPriv = (rfbDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ pScreen);
+ if (pPriv && (pCursor->bits->refcnt <= 1))
+ {
+ if (pPriv->sourceBits)
+ (*pScreen->DestroyPixmap) (pPriv->sourceBits);
+ if (pPriv->maskBits)
+ (*pScreen->DestroyPixmap) (pPriv->maskBits);
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ FreePicture (pPriv->pPicture, 0);
+#endif
+ xfree ((pointer) pPriv);
+ dixSetPrivate(&pCursor->bits->devPrivates, pScreen, NULL);
+ }
+ return TRUE;
+}
+
+static void
+rfbDCPutBits (DrawablePtr pDrawable, rfbDCCursorPtr pPriv, GCPtr sourceGC, GCPtr maskGC, int x, int y, unsigned w, unsigned h, unsigned long source, unsigned long mask)
+{
+ XID gcvals[1];
+
+ if (sourceGC->fgPixel != source)
+ {
+ gcvals[0] = source;
+ DoChangeGC (sourceGC, GCForeground, gcvals, 0);
+ }
+ if (sourceGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, sourceGC);
+ (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
+ if (maskGC->fgPixel != mask)
+ {
+ gcvals[0] = mask;
+ DoChangeGC (maskGC, GCForeground, gcvals, 0);
+ }
+ if (maskGC->serialNumber != pDrawable->serialNumber)
+ ValidateGC (pDrawable, maskGC);
+ (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
+}
+
+#define EnsureGC(gc,win) (gc || rfbDCMakeGC(&gc, win))
+
+static GCPtr
+rfbDCMakeGC(GCPtr *ppGC, WindowPtr pWin)
+{
+ GCPtr pGC;
+ int status;
+ XID gcvals[2];
+
+ gcvals[0] = IncludeInferiors;
+ gcvals[1] = FALSE;
+ pGC = CreateGC((DrawablePtr)pWin,
+ GCSubwindowMode|GCGraphicsExposures, gcvals, &status, (XID)0, serverClient);
+ if (pGC && pWin->drawable.pScreen->DrawGuarantee)
+ (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
+ *ppGC = pGC;
+ return pGC;
+}
+
+static Bool
+rfbDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+ int x, y;
+ unsigned long source, mask;
+{
+ rfbDCScreenPtr pScreenPriv;
+ rfbDCCursorPtr pPriv;
+ WindowPtr pWin;
+
+ pPriv = (rfbDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ pScreen);
+ if (!pPriv)
+ {
+ pPriv = rfbDCRealize(pScreen, pCursor);
+ if (!pPriv)
+ return FALSE;
+ }
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pWin = WindowTable[pScreen->myNum];
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ {
+ if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin))
+ return FALSE;
+ CompositePicture (PictOpOver,
+ pPriv->pPicture,
+ NULL,
+ pScreenPriv->pRootPicture,
+ 0, 0, 0, 0,
+ x, y,
+ pCursor->bits->width,
+ pCursor->bits->height);
+ }
+ else
+#endif
+ {
+ if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
+ return FALSE;
+ if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
+ {
+ FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
+ pScreenPriv->pSourceGC = 0;
+ return FALSE;
+ }
+ rfbDCPutBits ((DrawablePtr)pWin, pPriv,
+ pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
+ x, y, pCursor->bits->width, pCursor->bits->height,
+ source, mask);
+ }
+ return TRUE;
+}
+
+static Bool
+rfbDCSaveUnderCursor (pScreen, x, y, w, h)
+ ScreenPtr pScreen;
+ int x, y, w, h;
+{
+ rfbDCScreenPtr pScreenPriv;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pSave = pScreenPriv->pSave;
+ pWin = WindowTable[pScreen->myNum];
+ if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
+ {
+ if (pSave)
+ (*pScreen->DestroyPixmap) (pSave);
+ pScreenPriv->pSave = pSave =
+ (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
+ if (!pSave)
+ return FALSE;
+ }
+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
+ return FALSE;
+ pGC = pScreenPriv->pSaveGC;
+ if (pSave->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pSave, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y, w, h, 0, 0);
+ return TRUE;
+}
+
+static Bool
+rfbDCRestoreUnderCursor (pScreen, x, y, w, h)
+ ScreenPtr pScreen;
+ int x, y, w, h;
+{
+ rfbDCScreenPtr pScreenPriv;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pSave = pScreenPriv->pSave;
+ pWin = WindowTable[pScreen->myNum];
+ if (!pSave)
+ return FALSE;
+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+ return FALSE;
+ pGC = pScreenPriv->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, 0, w, h, x, y);
+ return TRUE;
+}
+
+static Bool
+rfbDCChangeSave (pScreen, x, y, w, h, dx, dy)
+ ScreenPtr pScreen;
+ int x, y, w, h, dx, dy;
+{
+ rfbDCScreenPtr pScreenPriv;
+ PixmapPtr pSave;
+ WindowPtr pWin;
+ GCPtr pGC;
+ int sourcex, sourcey, destx, desty, copyw, copyh;
+
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pSave = pScreenPriv->pSave;
+ pWin = WindowTable[pScreen->myNum];
+ /*
+ * restore the bits which are about to get trashed
+ */
+ if (!pSave)
+ return FALSE;
+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+ return FALSE;
+ pGC = pScreenPriv->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+ /*
+ * copy the old bits to the screen.
+ */
+ if (dy > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, h - dy, w, dy, x + dx, y + h);
+ }
+ else if (dy < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, 0, w, -dy, x + dx, y + dy);
+ }
+ if (dy >= 0)
+ {
+ desty = y + dy;
+ sourcey = 0;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = y;
+ sourcey = - dy;
+ copyh = h + dy;
+ }
+ if (dx > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ w - dx, sourcey, dx, copyh, x + w, desty);
+ }
+ else if (dx < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
+ 0, sourcey, -dx, copyh, x + dx, desty);
+ }
+ if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
+ return FALSE;
+ pGC = pScreenPriv->pSaveGC;
+ if (pSave->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pSave, pGC);
+ /*
+ * move the bits that are still valid within the pixmap
+ */
+ if (dx >= 0)
+ {
+ sourcex = 0;
+ destx = dx;
+ copyw = w - dx;
+ }
+ else
+ {
+ destx = 0;
+ sourcex = - dx;
+ copyw = w + dx;
+ }
+ if (dy >= 0)
+ {
+ sourcey = 0;
+ desty = dy;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = 0;
+ sourcey = -dy;
+ copyh = h + dy;
+ }
+ (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
+ sourcex, sourcey, copyw, copyh, destx, desty);
+ /*
+ * copy the new bits from the screen into the remaining areas of the
+ * pixmap
+ */
+ if (dy > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y, w, dy, 0, 0);
+ }
+ else if (dy < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, y + h + dy, w, -dy, 0, h + dy);
+ }
+ if (dy >= 0)
+ {
+ desty = dy;
+ sourcey = y + dy;
+ copyh = h - dy;
+ }
+ else
+ {
+ desty = 0;
+ sourcey = y;
+ copyh = h + dy;
+ }
+ if (dx > 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x, sourcey, dx, copyh, 0, desty);
+ }
+ else if (dx < 0)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
+ x + w + dx, sourcey, -dx, copyh, w + dx, desty);
+ }
+ return TRUE;
+}
+
+static Bool
+rfbDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+ int x, y, w, h, dx, dy;
+ unsigned long source, mask;
+{
+ rfbDCCursorPtr pPriv;
+ rfbDCScreenPtr pScreenPriv;
+ int status;
+ WindowPtr pWin;
+ GCPtr pGC;
+ XID gcval = FALSE;
+ PixmapPtr pTemp;
+
+ pPriv = (rfbDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates,
+ pScreen);
+ if (!pPriv)
+ {
+ pPriv = rfbDCRealize(pScreen, pCursor);
+ if (!pPriv)
+ return FALSE;
+ }
+ pScreenPriv = (rfbDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbDCScreenKey);
+ pWin = WindowTable[pScreen->myNum];
+ pTemp = pScreenPriv->pTemp;
+ if (!pTemp ||
+ pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
+ pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
+ {
+ if (pTemp)
+ (*pScreen->DestroyPixmap) (pTemp);
+#ifdef ARGB_CURSOR
+ if (pScreenPriv->pTempPicture)
+ {
+ FreePicture (pScreenPriv->pTempPicture, 0);
+ pScreenPriv->pTempPicture = 0;
+ }
+#endif
+ pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
+ (pScreen, w, h, pScreenPriv->pSave->drawable.depth, 0);
+ if (!pTemp)
+ return FALSE;
+ }
+ if (!pScreenPriv->pMoveGC)
+ {
+ pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pScreenPriv->pMoveGC)
+ return FALSE;
+ }
+ /*
+ * copy the saved area to a temporary pixmap
+ */
+ pGC = pScreenPriv->pMoveGC;
+ if (pGC->serialNumber != pTemp->drawable.serialNumber)
+ ValidateGC ((DrawablePtr) pTemp, pGC);
+ (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
+ (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
+
+ /*
+ * draw the cursor in the temporary pixmap
+ */
+#ifdef ARGB_CURSOR
+ if (pPriv->pPicture)
+ {
+ if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin))
+ return FALSE;
+ CompositePicture (PictOpOver,
+ pPriv->pPicture,
+ NULL,
+ pScreenPriv->pTempPicture,
+ 0, 0, 0, 0,
+ dx, dy,
+ pCursor->bits->width,
+ pCursor->bits->height);
+ }
+ else
+#endif
+ {
+ if (!pScreenPriv->pPixSourceGC)
+ {
+ pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pScreenPriv->pPixSourceGC)
+ return FALSE;
+ }
+ if (!pScreenPriv->pPixMaskGC)
+ {
+ pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
+ GCGraphicsExposures, &gcval, &status, (XID)0, serverClient);
+ if (!pScreenPriv->pPixMaskGC)
+ return FALSE;
+ }
+ rfbDCPutBits ((DrawablePtr)pTemp, pPriv,
+ pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
+ dx, dy, pCursor->bits->width, pCursor->bits->height,
+ source, mask);
+ }
+
+ /*
+ * copy the temporary pixmap onto the screen
+ */
+
+ if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
+ return FALSE;
+ pGC = pScreenPriv->pRestoreGC;
+ if (pWin->drawable.serialNumber != pGC->serialNumber)
+ ValidateGC ((DrawablePtr) pWin, pGC);
+
+ (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,
+ pGC,
+ 0, 0, w, h, x, y);
+ return TRUE;
+}
--- xorg-server-1.7.4/hw/vnc/dpmsstubs.c
+++ xorg-server-1.7.4/hw/vnc/dpmsstubs.c
@@ -0,0 +1,52 @@
+/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */
+/*****************************************************************
+
+Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+/* $XFree86: xc/programs/Xserver/Xext/dpmsstubs.c,v 3.3 1999/12/16 02:26:23 robin Exp $ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "rfb.h"
+
+#define FALSE 0
+
+Bool DPMSSupported(void)
+{
+ return FALSE;
+}
+
+int DPSMGet(int *level)
+{
+ return -1;
+}
+
+int DPMSSet(ClientPtr client, int level)
+{
+ return FALSE;
+}
--- xorg-server-1.7.4/hw/vnc/draw.c
+++ xorg-server-1.7.4/hw/vnc/draw.c
@@ -0,0 +1,2021 @@
+/*
+ * draw.c - drawing routines for the RFB X server. This is a set of
+ * wrappers around the standard MI/MFB/CFB drawing routines which work out
+ * to a fair approximation the region of the screen being modified by the
+ * drawing. If the RFB client is ready then the modified region of the screen
+ * is sent to the client, otherwise the modified region will simply grow with
+ * each drawing request until the client is ready.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1989 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.
+*/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "rfb.h"
+
+int rfbDeferUpdateTime = 40; /* ms */
+
+
+/****************************************************************************/
+/*
+ * Macro definitions
+ */
+/****************************************************************************/
+
+#define TRC(x) /* (rfbLog x) */
+
+/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each
+ client */
+
+#define ADD_TO_MODIFIED_REGION(pScreen,reg) \
+ { \
+ rfbClientPtr cl; \
+ for (cl = rfbClientHead; cl; cl = cl->next) { \
+ REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\
+ } \
+ }
+
+/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an
+ update to be sent to each client if there is one pending and the client is
+ ready for it. */
+
+#define SCHEDULE_FB_UPDATE(pScreen,pVNC) \
+ if (!pVNC->dontSendFramebufferUpdate) { \
+ rfbClientPtr cl, nextCl; \
+ for (cl = rfbClientHead; cl; cl = nextCl) { \
+ nextCl = cl->next; \
+ if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \
+ REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \
+ { \
+ rfbScheduleDeferredUpdate(pScreen, cl); \
+ } \
+ } \
+ }
+
+/* function prototypes */
+
+static void rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl);
+static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl,
+ RegionPtr src, RegionPtr dst, int dx, int dy);
+#ifdef DEBUG
+static void PrintRegion(ScreenPtr pScreen, RegionPtr reg);
+#endif
+
+/* GC funcs */
+
+static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr);
+static void rfbChangeGC(GCPtr, unsigned long /*mask*/);
+static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/);
+static void rfbDestroyGC(GCPtr);
+static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/,
+ int /*nrects*/);
+static void rfbDestroyClip(GCPtr);
+static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/);
+
+/* GC ops */
+
+static void rfbFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int fSorted);
+static void rfbSetSpans(DrawablePtr pDrawable,
+ GCPtr pGC,
+ char *psrc,
+ register DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ int fSorted);
+static void rfbPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits);
+static RegionPtr rfbCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty);
+static RegionPtr rfbCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, register GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane);
+static void rfbPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pts);
+static void rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts);
+static void rfbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *segs);
+static void rfbPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects);
+static void rfbPolyArc(DrawablePtr pDrawable, register GCPtr pGC, int narcs, xArc *arcs);
+static void rfbFillPolygon(register DrawablePtr pDrawable, register GCPtr pGC, int shape, int mode, int count, DDXPointPtr pts);
+static void rfbPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects);
+static void rfbPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *arcs);
+static int rfbPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars);
+static int rfbPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars);
+static void rfbImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars);
+static void rfbImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars);
+static void rfbImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase);
+static void rfbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase);
+static void rfbPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, int w, int h, int x, int y);
+
+
+static GCFuncs rfbGCFuncs = {
+ rfbValidateGC,
+ rfbChangeGC,
+ rfbCopyGC,
+ rfbDestroyGC,
+ rfbChangeClip,
+ rfbDestroyClip,
+ rfbCopyClip,
+};
+
+
+static GCOps rfbGCOps = {
+ rfbFillSpans, rfbSetSpans, rfbPutImage,
+ rfbCopyArea, rfbCopyPlane, rfbPolyPoint,
+ rfbPolylines, rfbPolySegment, rfbPolyRectangle,
+ rfbPolyArc, rfbFillPolygon, rfbPolyFillRect,
+ rfbPolyFillArc, rfbPolyText8, rfbPolyText16,
+ rfbImageText8, rfbImageText16, rfbImageGlyphBlt,
+ rfbPolyGlyphBlt, rfbPushPixels
+};
+
+
+
+/****************************************************************************/
+/*
+ * Screen functions wrapper stuff
+ */
+/****************************************************************************/
+
+#define SCREEN_PROLOGUE(scrn, field) \
+ ScreenPtr pScreen = scrn; \
+ VNCSCREENPTR(pScreen); \
+ pScreen->field = pVNC->field;
+
+#define SCREEN_EPILOGUE(field, wrapper) \
+ pScreen->field = wrapper;
+
+
+/*
+ * CloseScreen wrapper -- unwrap everything, free the private data
+ * and call the wrapped CloseScreen function.
+ */
+
+Bool
+rfbCloseScreen (int i, ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+#if XFREE86VNC
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+#endif
+ int sock;
+
+ for (sock = 0; sock <= pVNC->maxFd; sock++) {
+ if (FD_ISSET(sock, &pVNC->allFds))
+ if (sock != pVNC->rfbListenSock && sock != pVNC->httpListenSock) {
+ rfbCloseSock(pScreen, sock);
+ }
+ }
+
+ if (pVNC->rfbListenSock > 0)
+ if (close(pVNC->rfbListenSock))
+ ErrorF("Close of port %d failed\n",pVNC->rfbPort);
+
+ if (pVNC->httpListenSock > 0)
+ if (close(pVNC->httpListenSock))
+ ErrorF("Close of port %d failed\n",pVNC->httpPort);
+
+ pScreen->CloseScreen = pVNC->CloseScreen;
+ pScreen->CreateGC = pVNC->CreateGC;
+ pScreen->PaintWindowBackground = pVNC->PaintWindowBackground;
+ pScreen->PaintWindowBorder = pVNC->PaintWindowBorder;
+ pScreen->CopyWindow = pVNC->CopyWindow;
+ pScreen->ClearToBackground = pVNC->ClearToBackground;
+ pScreen->RestoreAreas = pVNC->RestoreAreas;
+ pScreen->WakeupHandler = pVNC->WakeupHandler;
+
+#if XFREE86VNC
+ pScreen->InstallColormap = pVNC->InstallColormap;
+ pScreen->UninstallColormap = pVNC->UninstallColormap;
+ pScreen->ListInstalledColormaps = pVNC->ListInstalledColormaps;
+ pScreen->StoreColors = pVNC->StoreColors;
+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess;
+
+ xfree(pVNC);
+#endif
+
+ TRC((stderr,"Unwrapped screen functions\n"));
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+#if XFREE86VNC
+void
+rfbEnableDisableFBAccess (int index, Bool enable)
+{
+ ScrnInfoPtr pScrn = xf86Screens[index];
+ VNCSCREENPTR(pScrn->pScreen);
+
+ /*
+ * Blank the screen for security while inputs are disabled.
+ * When VT switching is fixed, we might be able to allow
+ * control even when switched away.
+ */
+ if (!enable) {
+ WindowPtr pWin = WindowTable[index];
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ GCPtr pGC;
+ xRectangle rect;
+
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = pScrn->virtualX;
+ rect.height = pScrn->virtualY;
+
+ if (!(pGC = GetScratchGC(pScreen->rootDepth, pScreen))) {
+ ErrorF("Couldn't blank screen");
+ } else {
+ CARD32 attributes[2];
+ attributes[0] = pScreen->whitePixel;
+ attributes[1] = pScreen->blackPixel;
+ (void)ChangeGC(pGC, GCForeground | GCBackground, attributes);
+
+ ValidateGC((DrawablePtr)pWin, pGC);
+
+ (*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, 1, &rect);
+
+ FreeScratchGC(pGC);
+
+ /* Flush pending packets */
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+ }
+ }
+
+ pScrn->EnableDisableFBAccess = pVNC->EnableDisableFBAccess;
+ (*pScrn->EnableDisableFBAccess)(index, enable);
+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess;
+}
+#endif
+
+/*
+ * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC
+ * func "ValidateGC" is called).
+ */
+
+Bool
+rfbCreateGC (GCPtr pGC)
+{
+ Bool ret;
+ rfbGCPtr pGCPriv;
+
+ SCREEN_PROLOGUE(pGC->pScreen,CreateGC);
+
+ pGCPriv = (rfbGCPtr)
+ dixLookupPrivate(&(pGC)->devPrivates, rfbGCKey);
+
+ ret = (*pScreen->CreateGC) (pGC);
+
+ TRC((stderr,"rfbCreateGC called\n"));
+
+ pGCPriv->wrapOps = NULL;
+ pGCPriv->wrapFuncs = pGC->funcs;
+ pGC->funcs = &rfbGCFuncs;
+
+ SCREEN_EPILOGUE(CreateGC,rfbCreateGC);
+
+ return ret;
+}
+
+/*
+ * PaintWindowBackground - the region being modified is just the given region.
+ */
+
+void
+rfbPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground);
+
+ TRC((stderr,"rfbPaintWindowBackground called\n"));
+
+ ADD_TO_MODIFIED_REGION(pScreen,pRegion);
+
+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
+
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+
+ SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground);
+}
+
+/*
+ * PaintWindowBorder - the region being modified is just the given region.
+ */
+
+void
+rfbPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
+{
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder);
+
+ TRC((stderr,"rfbPaintWindowBorder called\n"));
+
+ ADD_TO_MODIFIED_REGION(pScreen,pRegion);
+
+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
+
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+
+ SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder);
+}
+
+#ifdef CHROMIUM
+Bool
+rfbRealizeWindow(WindowPtr pWin)
+{
+ CRWindowTable *wt = NULL, *nextWt = NULL;
+ Bool ret;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RealizeWindow);
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ rfbSendChromiumWindowShow(wt->CRwinId, 1);
+ }
+ }
+
+ ret = (*pScreen->RealizeWindow)(pWin);
+
+ SCREEN_EPILOGUE(RealizeWindow,rfbRealizeWindow);
+
+ return ret;
+}
+
+Bool
+rfbUnrealizeWindow(WindowPtr pWin)
+{
+ CRWindowTable *wt = NULL, *nextWt = NULL;
+ Bool ret;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,UnrealizeWindow);
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ rfbSendChromiumWindowShow(wt->CRwinId, 0);
+ }
+ }
+
+ ret = (*pScreen->UnrealizeWindow)(pWin);
+
+ SCREEN_EPILOGUE(UnrealizeWindow,rfbUnrealizeWindow);
+
+ return ret;
+}
+
+Bool
+rfbDestroyWindow(WindowPtr pWin)
+{
+ CRWindowTable *wt = NULL, *nextWt = NULL, *prevWt = NULL;
+ Bool ret;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,DestroyWindow);
+
+ /* loop over monitored windows */
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ rfbSendChromiumWindowDestroy(wt->CRwinId);
+ /* also remove from list */
+ if (prevWt)
+ prevWt->next = wt->next;
+ else
+ windowTable = wt->next;
+ xfree(wt);
+ }
+ else {
+ prevWt = wt;
+ }
+ }
+
+ ret = (*pScreen->DestroyWindow)(pWin);
+
+ SCREEN_EPILOGUE(DestroyWindow,rfbDestroyWindow);
+
+ return ret;
+}
+
+void
+rfbResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ CRWindowTable *wt = NULL, *nextWt = NULL;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ResizeWindow);
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, pWin->drawable.x, pWin->drawable.y, w, h);
+ }
+ }
+
+ (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
+
+ SCREEN_EPILOGUE(ResizeWindow,rfbResizeWindow);
+}
+
+Bool
+rfbPositionWindow(WindowPtr pWin, int x, int y)
+{
+ Bool ret;
+ CRWindowTable *wt, *nextWt;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,PositionWindow);
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ rfbSendChromiumMoveResizeWindow(wt->CRwinId, x, y, pWin->drawable.width, pWin->drawable.height);
+ }
+ }
+
+ ret = (*pScreen->PositionWindow)(pWin, x, y);
+
+ SCREEN_EPILOGUE(PositionWindow,rfbPositionWindow);
+
+ return ret;
+}
+
+void
+rfbClipNotify(WindowPtr pWin, int x, int y)
+{
+ CRWindowTable *wt, *nextWt;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClipNotify);
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == pWin->drawable.id) {
+ int numClipRects = REGION_NUM_RECTS(&pWin->clipList);
+ BoxPtr pClipRects = REGION_RECTS(&pWin->clipList);
+
+ /* Possible optimization - has the cliplist really? changed */
+
+ rfbSendChromiumClipList(wt->CRwinId, pClipRects, numClipRects);
+ }
+ }
+
+ if (*pScreen->ClipNotify)
+ (*pScreen->ClipNotify)(pWin, x, y);
+
+ SCREEN_EPILOGUE(ClipNotify,rfbClipNotify);
+}
+#endif /* CHROMIUM */
+
+/*
+ * CopyWindow - the region being modified is the translation of the old
+ * region, clipped to the border clip region of the window. Note that any
+ * parts of the window which have become newly-visible will not be affected by
+ * this call - a separate PaintWindowBackground/Border will be called to do
+ * that. If the client will accept CopyRect messages then use rfbCopyRegion to
+ * optimise the pending screen changes into a single "copy region" plus the
+ * ordinary modified region.
+ */
+
+void
+rfbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr pOldRegion)
+{
+ rfbClientPtr cl;
+ RegionRec srcRegion, dstRegion;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow);
+
+ TRC((stderr,"rfbCopyWindow called\n"));
+
+ REGION_NULL(pScreen,&dstRegion);
+ REGION_COPY(pScreen,&dstRegion,pOldRegion);
+ REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion,
+ pWin->drawable.x - ptOldOrg.x,
+ pWin->drawable.y - ptOldOrg.y);
+ REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion,
+ &pWin->borderClip);
+
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ if (cl->useCopyRect) {
+ REGION_NULL(pScreen,&srcRegion);
+ REGION_COPY(pScreen,&srcRegion,pOldRegion);
+
+ rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion,
+ pWin->drawable.x - ptOldOrg.x,
+ pWin->drawable.y - ptOldOrg.y);
+
+ REGION_UNINIT(pScreen, &srcRegion);
+
+ } else {
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &dstRegion);
+ }
+ }
+
+ REGION_UNINIT(pScreen, &dstRegion);
+
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
+
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+
+ SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow);
+}
+
+/*
+ * ClearToBackground - when generateExposures is false, the region being
+ * modified is the given rectangle (clipped to the "window clip region").
+ */
+
+void
+rfbClearToBackground (WindowPtr pWin, int x, int y, int w, int h,
+ Bool generateExposures)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground);
+
+ TRC((stderr,"rfbClearToBackground called\n"));
+
+ if (!generateExposures) {
+ box.x1 = x + pWin->drawable.x;
+ box.y1 = y + pWin->drawable.y;
+ box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
+ box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
+
+ SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList);
+
+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion);
+
+ REGION_UNINIT(pScreen, &tmpRegion);
+ }
+
+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
+
+ if (!generateExposures) {
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+ }
+
+ SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground);
+}
+
+/*
+ * RestoreAreas - just be safe here - the region being modified is the whole
+ * exposed region.
+ */
+
+RegionPtr
+rfbRestoreAreas (WindowPtr pWin, RegionPtr prgnExposed)
+{
+ RegionPtr result;
+ SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas);
+
+ TRC((stderr,"rfbRestoreAreas called\n"));
+
+ ADD_TO_MODIFIED_REGION(pScreen, prgnExposed);
+
+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
+
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+
+ SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas);
+
+ return result;
+}
+
+
+
+/****************************************************************************/
+/*
+ * GC funcs wrapper stuff
+ *
+ * We only really want to wrap the GC ops, but to do this we need to wrap
+ * ValidateGC and so all the other GC funcs must be wrapped as well.
+ */
+/****************************************************************************/
+
+#define GC_FUNC_PROLOGUE(pGC) \
+ rfbGCPtr pGCPriv = (rfbGCPtr)dixLookupPrivate(&(pGC)->devPrivates, rfbGCKey); \
+ (pGC)->funcs = pGCPriv->wrapFuncs; \
+ if (pGCPriv->wrapOps) \
+ (pGC)->ops = pGCPriv->wrapOps;
+
+#define GC_FUNC_EPILOGUE(pGC) \
+ pGCPriv->wrapFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rfbGCFuncs; \
+ if (pGCPriv->wrapOps) { \
+ pGCPriv->wrapOps = (pGC)->ops; \
+ (pGC)->ops = &rfbGCOps; \
+ }
+
+
+/*
+ * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if
+ * the drawing will be to a viewable window.
+ */
+
+static void
+rfbValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ GC_FUNC_PROLOGUE(pGC);
+
+ TRC((stderr,"rfbValidateGC called\n"));
+
+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
+
+ pGCPriv->wrapOps = NULL;
+ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable)
+ {
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ RegionPtr pRegion = &pWin->clipList;
+
+ if (pGC->subWindowMode == IncludeInferiors)
+ pRegion = &pWin->borderClip;
+ if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) {
+ pGCPriv->wrapOps = pGC->ops;
+ TRC((stderr,"rfbValidateGC: wrapped GC ops\n"));
+ }
+ }
+
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+/*
+ * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped
+ * function and then rewrap the funcs and ops.
+ */
+
+static void
+rfbChangeGC (pGC, mask)
+ GCPtr pGC;
+ unsigned long mask;
+{
+ GC_FUNC_PROLOGUE(pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+static void
+rfbCopyGC (pGCSrc, mask, pGCDst)
+ GCPtr pGCSrc, pGCDst;
+ unsigned long mask;
+{
+ GC_FUNC_PROLOGUE(pGCDst);
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ GC_FUNC_EPILOGUE(pGCDst);
+}
+
+static void
+rfbDestroyGC (pGC)
+ GCPtr pGC;
+{
+ GC_FUNC_PROLOGUE(pGC);
+ (*pGC->funcs->DestroyGC) (pGC);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+static void
+rfbChangeClip (pGC, type, pvalue, nrects)
+ GCPtr pGC;
+ int type;
+ pointer pvalue;
+ int nrects;
+{
+ GC_FUNC_PROLOGUE(pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+static void
+rfbDestroyClip(pGC)
+ GCPtr pGC;
+{
+ GC_FUNC_PROLOGUE(pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ GC_FUNC_EPILOGUE(pGC);
+}
+
+static void
+rfbCopyClip(pgcDst, pgcSrc)
+ GCPtr pgcDst, pgcSrc;
+{
+ GC_FUNC_PROLOGUE(pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ GC_FUNC_EPILOGUE(pgcDst);
+}
+
+
+/****************************************************************************/
+/*
+ * GC ops wrapper stuff
+ *
+ * Note that these routines will only have been wrapped for drawing to
+ * viewable windows so we don't need to check each time that the drawable
+ * is a viewable window.
+ */
+/****************************************************************************/
+
+#define GC_OP_PROLOGUE(pDrawable,pGC) \
+ ScreenPtr pScreen = pGC->pScreen; \
+ VNCSCREENPTR(pScreen); \
+ rfbGCPtr pGCPrivate = (rfbGCPtr)dixLookupPrivate(&(pGC)->devPrivates, rfbGCKey); \
+ GCFuncs *oldFuncs = pGC->funcs; \
+ (void) pScreen; /* silence compiler */ \
+ (pGC)->funcs = pGCPrivate->wrapFuncs; \
+ (pGC)->ops = pGCPrivate->wrapOps;
+
+#define GC_OP_EPILOGUE(pGC) \
+ pGCPrivate->wrapOps = (pGC)->ops; \
+ (pGC)->funcs = oldFuncs; \
+ (pGC)->ops = &rfbGCOps;
+
+
+/*
+ * FillSpans - being very safe - the region being modified is the border clip
+ * region of the window.
+ */
+
+static void
+rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nInit; /* number of spans to fill */
+ DDXPointPtr pptInit; /* pointer to list of start points */
+ int *pwidthInit; /* pointer to list of n widths */
+ int fSorted;
+{
+ GC_OP_PROLOGUE(pDrawable,pGC);
+
+ TRC((stderr,"rfbFillSpans called\n"));
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen,
+ &((WindowPtr)pDrawable)->borderClip);
+
+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted);
+
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * SetSpans - being very safe - the region being modified is the border clip
+ * region of the window.
+ */
+
+static void
+rfbSetSpans(DrawablePtr pDrawable,
+ GCPtr pGC,
+ char *psrc,
+ register DDXPointPtr ppt,
+ int *pwidth,
+ int nspans,
+ int fSorted)
+{
+ GC_OP_PROLOGUE(pDrawable,pGC);
+
+ TRC((stderr,"rfbSetSpans called\n"));
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen,
+ &((WindowPtr)pDrawable)->borderClip);
+
+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PutImage - the region being modified is the rectangle of the
+ * PutImage (clipped to the window clip region).
+ */
+
+static void
+rfbPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPutImage called\n"));
+
+ box.x1 = x + pDrawable->x;
+ box.y1 = y + pDrawable->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+
+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h,
+ leftPad, format, pBits);
+
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * CopyArea - the region being modified is the destination rectangle (clipped
+ * to the window clip region).
+ * If the client will accept CopyRect messages then use rfbCopyRegion
+ * to optimise the pending screen changes into a single "copy region" plus
+ * the ordinary modified region.
+ */
+
+static RegionPtr
+rfbCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty)
+{
+ rfbClientPtr cl;
+ RegionPtr rgn;
+ RegionRec srcRegion, dstRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDst, pGC);
+
+ TRC((stderr,"rfbCopyArea called\n"));
+
+ box.x1 = dstx + pDst->x;
+ box.y1 = dsty + pDst->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0);
+ REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion,
+ pGC->pCompositeClip);
+
+ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) {
+ box.x1 = srcx + pSrc->x;
+ box.y1 = srcy + pSrc->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ if (cl->useCopyRect) {
+ SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0);
+ REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion,
+ &((WindowPtr)pSrc)->clipList);
+
+ rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion,
+ dstx + pDst->x - srcx - pSrc->x,
+ dsty + pDst->y - srcy - pSrc->y);
+
+ REGION_UNINIT(pSrc->pScreen, &srcRegion);
+
+ } else {
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &dstRegion);
+ }
+ }
+
+ } else {
+
+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion);
+ }
+
+ REGION_UNINIT(pDst->pScreen, &dstRegion);
+
+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty);
+
+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+
+ return rgn;
+}
+
+
+/*
+ * CopyPlane - the region being modified is the destination rectangle (clipped
+ * to the window clip region).
+ */
+
+static RegionPtr
+rfbCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, register GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane)
+{
+ RegionPtr rgn;
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDst, pGC);
+
+ TRC((stderr,"rfbCopyPlane called\n"));
+
+ box.x1 = dstx + pDst->x;
+ box.y1 = dsty + pDst->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDst->pScreen, &tmpRegion);
+
+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ SCHEDULE_FB_UPDATE(pDst->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+
+ return rgn;
+}
+
+/*
+ * PolyPoint - find the smallest rectangle which encloses the points drawn
+ * (and clip).
+ */
+
+static void
+rfbPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pts)
+{
+ int i;
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyPoint called\n"));
+
+ if (npt) {
+ int minX = pts[0].x, maxX = pts[0].x;
+ int minY = pts[0].y, maxY = pts[0].y;
+
+ if (mode == CoordModePrevious)
+ {
+ int x = pts[0].x, y = pts[0].y;
+
+ for (i = 1; i < npt; i++) {
+ x += pts[i].x;
+ y += pts[i].y;
+ if (x < minX) minX = x;
+ if (x > maxX) maxX = x;
+ if (y < minY) minY = y;
+ if (y > maxY) maxY = y;
+ }
+ }
+ else
+ {
+ for (i = 1; i < npt; i++) {
+ if (pts[i].x < minX) minX = pts[i].x;
+ if (pts[i].x > maxX) maxX = pts[i].x;
+ if (pts[i].y < minY) minY = pts[i].y;
+ if (pts[i].y > maxY) maxY = pts[i].y;
+ }
+ }
+
+ box.x1 = minX + pDrawable->x;
+ box.y1 = minY + pDrawable->y;
+ box.x2 = maxX + 1 + pDrawable->x;
+ box.y2 = maxY + 1 + pDrawable->y;
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
+
+ if (npt) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyLines - take the union of bounding boxes around each line (and clip).
+ */
+
+static void
+rfbPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppts)
+{
+ RegionPtr tmpRegion;
+ xRectangle *rects;
+ int i, extra, nlines, lw;
+ int x1, x2, y1, y2;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolylines called\n"));
+
+ if (npt) {
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ lw = 1;
+
+ if (npt == 1)
+ {
+ nlines = 1;
+ rects = (xRectangle *)xalloc(sizeof(xRectangle));
+ if (!rects) {
+ FatalError("rfbPolylines: xalloc failed\n");
+ }
+
+ rects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe here */
+ rects[0].y = ppts[0].y - lw + pDrawable->y;
+ rects[0].width = 2*lw;
+ rects[0].height = 2*lw;
+ }
+ else
+ {
+ nlines = npt - 1;
+ rects = (xRectangle *)xalloc(nlines*sizeof(xRectangle));
+ if (!rects) {
+ FatalError("rfbPolylines: xalloc failed\n");
+ }
+
+ /*
+ * mitered joins can project quite a way from
+ * the line end; the 11 degree miter limit limits
+ * this extension to lw / (2 * tan(11/2)), rounded up
+ * and converted to int yields 6 * lw
+ */
+
+ if (pGC->joinStyle == JoinMiter) {
+ extra = 6 * lw;
+ } else {
+ extra = lw / 2;
+ }
+
+ x1 = ppts[0].x + pDrawable->x;
+ y1 = ppts[0].y + pDrawable->y;
+
+ for (i = 0; i < nlines; i++) {
+ if (mode == CoordModeOrigin) {
+ x2 = pDrawable->x + ppts[i+1].x;
+ y2 = pDrawable->y + ppts[i+1].y;
+ } else {
+ x2 = x1 + ppts[i+1].x;
+ y2 = y1 + ppts[i+1].y;
+ }
+
+ if (x1 > x2) {
+ rects[i].x = x2 - extra;
+ rects[i].width = x1 - x2 + 1 + 2 * extra;
+ } else {
+ rects[i].x = x1 - extra;
+ rects[i].width = x2 - x1 + 1 + 2 * extra;
+ }
+
+ if (y1 > y2) {
+ rects[i].y = y2 - extra;
+ rects[i].height = y1 - y2 + 1 + 2 * extra;
+ } else {
+ rects[i].y = y1 - extra;
+ rects[i].height = y2 - y1 + 1 + 2 * extra;
+ }
+
+ x1 = x2;
+ y1 = y2;
+ }
+ }
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nlines, rects,CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)rects);
+ }
+
+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
+
+ if (npt) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolySegment - take the union of bounding boxes around each segment (and
+ * clip).
+ */
+
+static void
+rfbPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *segs)
+{
+ RegionPtr tmpRegion;
+ xRectangle *rects;
+ int i, extra, lw;
+
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolySegment called\n"));
+
+ if (nseg) {
+ rects = (xRectangle *)xalloc(nseg*sizeof(xRectangle));
+ if (!rects) {
+ FatalError("rfbPolySegment: xalloc failed\n");
+ }
+
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ lw = 1;
+
+ extra = lw / 2;
+
+ for (i = 0; i < nseg; i++)
+ {
+ if (segs[i].x1 > segs[i].x2) {
+ rects[i].x = segs[i].x2 - extra + pDrawable->x;
+ rects[i].width = segs[i].x1 - segs[i].x2 + 1 + 2 * extra;
+ } else {
+ rects[i].x = segs[i].x1 - extra + pDrawable->x;
+ rects[i].width = segs[i].x2 - segs[i].x1 + 1 + 2 * extra;
+ }
+
+ if (segs[i].y1 > segs[i].y2) {
+ rects[i].y = segs[i].y2 - extra + pDrawable->y;
+ rects[i].height = segs[i].y1 - segs[i].y2 + 1 + 2 * extra;
+ } else {
+ rects[i].y = segs[i].y1 - extra + pDrawable->y;
+ rects[i].height = segs[i].y2 - segs[i].y1 + 1 + 2 * extra;
+ }
+ }
+
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nseg, rects, CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)rects);
+ }
+
+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
+
+ if (nseg) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyRectangle (rectangle outlines) - take the union of bounding boxes
+ * around each line (and clip).
+ */
+
+static void
+rfbPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects)
+{
+ int i, extra, lw;
+ RegionPtr tmpRegion;
+ xRectangle *regRects;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyRectangle called\n"));
+
+ if (nrects) {
+ regRects = (xRectangle *)xalloc(nrects*4*sizeof(xRectangle));
+ if (!regRects) {
+ FatalError("rfbPolyRectangle: xalloc failed\n");
+ }
+
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ lw = 1;
+
+ extra = lw / 2;
+
+ for (i = 0; i < nrects; i++)
+ {
+ regRects[i*4].x = rects[i].x - extra + pDrawable->x;
+ regRects[i*4].y = rects[i].y - extra + pDrawable->y;
+ regRects[i*4].width = rects[i].width + 1 + 2 * extra;
+ regRects[i*4].height = 1 + 2 * extra;
+
+ regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
+ regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
+ regRects[i*4+1].width = 1 + 2 * extra;
+ regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
+
+ regRects[i*4+2].x
+ = rects[i].x + rects[i].width - extra + pDrawable->x;
+ regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
+ regRects[i*4+2].width = 1 + 2 * extra;
+ regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
+
+ regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
+ regRects[i*4+3].y
+ = rects[i].y + rects[i].height - extra + pDrawable->y;
+ regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
+ regRects[i*4+3].height = 1 + 2 * extra;
+ }
+
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects*4,
+ regRects, CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)regRects);
+ }
+
+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
+
+ if (nrects) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyArc - take the union of bounding boxes around each arc (and clip).
+ * Bounding boxes assume each is a full circle / ellipse.
+ */
+
+static void
+rfbPolyArc(DrawablePtr pDrawable, register GCPtr pGC, int narcs, xArc *arcs)
+{
+ int i, extra, lw;
+ RegionPtr tmpRegion;
+ xRectangle *rects;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyArc called\n"));
+
+ if (narcs) {
+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle));
+ if (!rects) {
+ FatalError("rfbPolyArc: xalloc failed\n");
+ }
+
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ lw = 1;
+
+ extra = lw / 2;
+
+ for (i = 0; i < narcs; i++)
+ {
+ rects[i].x = arcs[i].x - extra + pDrawable->x;
+ rects[i].y = arcs[i].y - extra + pDrawable->y;
+ rects[i].width = arcs[i].width + lw;
+ rects[i].height = arcs[i].height + lw;
+ }
+
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)rects);
+ }
+
+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
+
+ if (narcs) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * FillPolygon - take bounding box around polygon (and clip).
+ */
+
+static void
+rfbFillPolygon(register DrawablePtr pDrawable, register GCPtr pGC, int shape, int mode, int count, DDXPointPtr pts)
+{
+ int i;
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbFillPolygon called\n"));
+
+ if (count) {
+ int minX = pts[0].x, maxX = pts[0].x;
+ int minY = pts[0].y, maxY = pts[0].y;
+
+ if (mode == CoordModePrevious)
+ {
+ int x = pts[0].x, y = pts[0].y;
+
+ for (i = 1; i < count; i++) {
+ x += pts[i].x;
+ y += pts[i].y;
+ if (x < minX) minX = x;
+ if (x > maxX) maxX = x;
+ if (y < minY) minY = y;
+ if (y > maxY) maxY = y;
+ }
+ }
+ else
+ {
+ for (i = 1; i < count; i++) {
+ if (pts[i].x < minX) minX = pts[i].x;
+ if (pts[i].x > maxX) maxX = pts[i].x;
+ if (pts[i].y < minY) minY = pts[i].y;
+ if (pts[i].y > maxY) maxY = pts[i].y;
+ }
+ }
+
+ box.x1 = minX + pDrawable->x;
+ box.y1 = minY + pDrawable->y;
+ box.x2 = maxX + 1 + pDrawable->x;
+ box.y2 = maxY + 1 + pDrawable->y;
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
+
+ if (count) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyFillRect - take the union of the given rectangles (and clip).
+ */
+
+static void
+rfbPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, xRectangle *rects)
+{
+ RegionPtr tmpRegion;
+ xRectangle *regRects;
+ int i;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyFillRect called\n"));
+
+ if (nrects) {
+ regRects = (xRectangle *)xalloc(nrects*sizeof(xRectangle));
+ if (!regRects) {
+ FatalError("rfbPolyFillRect: xalloc failed\n");
+ }
+
+ for (i = 0; i < nrects; i++) {
+ regRects[i].x = rects[i].x + pDrawable->x;
+ regRects[i].y = rects[i].y + pDrawable->y;
+ regRects[i].width = rects[i].width;
+ regRects[i].height = rects[i].height;
+ }
+
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nrects, regRects,
+ CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)regRects);
+ }
+
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
+
+ if (nrects) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyFillArc - take the union of bounding boxes around each arc (and clip).
+ * Bounding boxes assume each is a full circle / ellipse.
+ */
+
+static void
+rfbPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *arcs)
+{
+ int i, extra, lw;
+ RegionPtr tmpRegion;
+ xRectangle *rects;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyFillArc called\n"));
+
+ if (narcs) {
+ rects = (xRectangle *)xalloc(narcs*sizeof(xRectangle));
+ if (!rects) {
+ FatalError("rfbPolyFillArc: xalloc failed\n");
+ }
+
+ lw = pGC->lineWidth;
+ if (lw == 0)
+ lw = 1;
+
+ extra = lw / 2;
+
+ for (i = 0; i < narcs; i++)
+ {
+ rects[i].x = arcs[i].x - extra + pDrawable->x;
+ rects[i].y = arcs[i].y - extra + pDrawable->y;
+ rects[i].width = arcs[i].width + lw;
+ rects[i].height = arcs[i].height + lw;
+ }
+
+ tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, narcs, rects, CT_NONE);
+ REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
+
+ REGION_DESTROY(pDrawable->pScreen, tmpRegion);
+ xfree((char *)rects);
+ }
+
+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
+
+ if (narcs) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * Get a rough bounding box around n characters of the given font.
+ */
+
+static void GetTextBoundingBox(DrawablePtr pDrawable, FontPtr font, int x, int y, int n, BoxPtr pbox)
+{
+ int maxAscent, maxDescent, maxCharWidth;
+
+ if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
+ maxAscent = FONTASCENT(font);
+ else
+ maxAscent = FONTMAXBOUNDS(font,ascent);
+
+ if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
+ maxDescent = FONTDESCENT(font);
+ else
+ maxDescent = FONTMAXBOUNDS(font,descent);
+
+ if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth))
+ maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing);
+ else
+ maxCharWidth = FONTMAXBOUNDS(font,characterWidth);
+
+ pbox->x1 = pDrawable->x + x;
+ pbox->y1 = pDrawable->y + y - maxAscent;
+ pbox->x2 = pbox->x1 + maxCharWidth * n;
+ pbox->y2 = pbox->y1 + maxAscent + maxDescent;
+
+ if (FONTMINBOUNDS(font,leftSideBearing) < 0) {
+ pbox->x1 += FONTMINBOUNDS(font,leftSideBearing);
+ }
+}
+
+
+/*
+ * PolyText8 - use rough bounding box.
+ */
+
+static int
+rfbPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars)
+{
+ int ret;
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyText8 called '%.*s'\n",count,chars));
+
+ if (count) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+ if (count) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+ return ret;
+}
+
+/*
+ * PolyText16 - use rough bounding box.
+ */
+
+static int
+rfbPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars)
+{
+ int ret;
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyText16 called\n"));
+
+ if (count) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+ if (count) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+ return ret;
+}
+
+/*
+ * ImageText8 - use rough bounding box.
+ */
+
+static void
+rfbImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbImageText8 called '%.*s'\n",count,chars));
+
+ if (count) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+
+ if (count) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * ImageText16 - use rough bounding box.
+ */
+
+static void
+rfbImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbImageText16 called\n"));
+
+ if (count) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+
+ if (count) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * ImageGlyphBlt - use rough bounding box.
+ */
+
+static void
+rfbImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbImageGlyphBlt called\n"));
+
+ if (nglyph) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
+
+ if (nglyph) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PolyGlyphBlt - use rough bounding box.
+ */
+
+static void
+rfbPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPolyGlyphBlt called\n"));
+
+ if (nglyph) {
+ GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+ }
+
+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ if (nglyph) {
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+ }
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+/*
+ * PushPixels - be fairly safe - region modified is intersection of the given
+ * rectangle with the window clip region.
+ */
+
+static void
+rfbPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+ RegionRec tmpRegion;
+ BoxRec box;
+ GC_OP_PROLOGUE(pDrawable, pGC);
+
+ TRC((stderr,"rfbPushPixels called\n"));
+
+ box.x1 = x + pDrawable->x;
+ box.y1 = y + pDrawable->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
+
+ REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
+ pGC->pCompositeClip);
+
+ ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
+
+ REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
+
+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
+
+ SCHEDULE_FB_UPDATE(pDrawable->pScreen, pVNC);
+
+ GC_OP_EPILOGUE(pGC);
+}
+
+#ifdef RENDER
+void
+rfbComposite(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height
+){
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ VNCSCREENPTR(pScreen);
+ RegionRec tmpRegion;
+ BoxRec box;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ box.x1 = pDst->pDrawable->x + xDst;
+ box.y1 = pDst->pDrawable->y + yDst;
+ box.x2 = box.x1 + width;
+ box.y2 = box.y1 + height;
+
+ REGION_INIT(pScreen, &tmpRegion, &box, 0);
+
+ ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion);
+
+ ps->Composite = pVNC->Composite;
+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ ps->Composite = rfbComposite;
+
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+
+ REGION_UNINIT(pScreen, &tmpRegion);
+}
+#endif /* RENDER */
+
+/****************************************************************************/
+/*
+ * Other functions
+ */
+/****************************************************************************/
+
+/*
+ * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy).
+ * Takes these args together with the existing modified region and possibly an
+ * existing copy region and translation. Produces a combined modified region
+ * plus copy region and translation. Note that the copy region is the
+ * destination of the copy.
+ *
+ * First we trim parts of src which are invalid (ie in the modified region).
+ * Then we see if there is any overlap between the src and the existing copy
+ * region. If not then the two copies cannot be combined, so we choose
+ * whichever is bigger to form the basis of a new copy, while the other copy is
+ * just done the hard way by being added to the modified region. So if the
+ * existing copy is bigger then we simply add the destination of the new copy
+ * to the modified region and we're done. If the new copy is bigger, we add
+ * the old copy region to the modified region and behave as though there is no
+ * existing copy region.
+ *
+ * At this stage we now know that either the two copies can be combined, or
+ * that there is no existing copy. We temporarily add both the existing copy
+ * region and dst to the modified region (this is the entire area of the screen
+ * affected in any way). Finally we calculate the new copy region, and remove
+ * it from the modified region.
+ *
+ * Note:
+ * 1. The src region is modified by this routine.
+ * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero.
+ */
+
+static void
+rfbCopyRegion(pScreen, cl, src, dst, dx, dy)
+ ScreenPtr pScreen;
+ rfbClientPtr cl;
+ RegionPtr src;
+ RegionPtr dst;
+ int dx, dy;
+{
+ RegionRec tmp;
+
+ /* src = src - modifiedRegion */
+
+ REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion);
+
+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
+
+ REGION_NULL(pScreen, &tmp);
+ REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion);
+
+ if (REGION_NOTEMPTY(pScreen, &tmp)) {
+
+ /* if src and copyRegion overlap:
+ src = src intersect copyRegion */
+
+ REGION_COPY(pScreen, src, &tmp);
+
+ } else {
+
+ /* if no overlap, find bigger region */
+
+ int newArea = (((REGION_EXTENTS(pScreen,src))->x2
+ - (REGION_EXTENTS(pScreen,src))->x1)
+ * ((REGION_EXTENTS(pScreen,src))->y2
+ - (REGION_EXTENTS(pScreen,src))->y1));
+
+ int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2
+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1)
+ * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2
+ - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1));
+
+ if (oldArea > newArea) {
+
+ /* existing copy is bigger:
+ modifiedRegion = modifiedRegion union dst
+ copyRegion = copyRegion - dst
+ return */
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ dst);
+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion,
+ dst);
+ if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+ }
+ return;
+ }
+
+ /* new copy is bigger:
+ modifiedRegion = modifiedRegion union copyRegion
+ copyRegion = empty */
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &cl->copyRegion);
+ REGION_EMPTY(pScreen, &cl->copyRegion);
+ cl->copyDX = cl->copyDY = 0;
+ }
+ }
+
+
+ /* modifiedRegion = modifiedRegion union dst union copyRegion */
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst);
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &cl->copyRegion);
+
+ /* copyRegion = T(src) intersect dst */
+
+ REGION_TRANSLATE(pScreen, src, dx, dy);
+ REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst);
+
+ /* modifiedRegion = modifiedRegion - copyRegion */
+
+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &cl->copyRegion);
+
+ /* combine new translation T with existing translation */
+
+ if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
+ cl->copyDX += dx;
+ cl->copyDY += dy;
+ } else {
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+ }
+}
+
+
+/*
+ * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer
+ * goes off.
+ */
+
+static CARD32
+rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ rfbClientPtr cl = (rfbClientPtr)arg;
+
+ rfbSendFramebufferUpdate(cl->pScreen, cl);
+
+ cl->deferredUpdateScheduled = FALSE;
+ return 0;
+}
+
+
+/*
+ * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro
+ * to schedule an update.
+ */
+
+static void
+rfbScheduleDeferredUpdate(ScreenPtr pScreen, rfbClientPtr cl)
+{
+ if (rfbDeferUpdateTime != 0) {
+ cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0,
+ rfbDeferUpdateTime,
+ rfbDeferredUpdateCallback, cl);
+ cl->deferredUpdateScheduled = TRUE;
+ } else {
+ rfbSendFramebufferUpdate(pScreen, cl);
+ }
+}
+
+
+/*
+ * PrintRegion is useful for debugging.
+ */
+
+#ifdef DEBUG
+static void
+PrintRegion(ScreenPtr pScreen, RegionPtr reg)
+{
+ int nrects = REGION_NUM_RECTS(reg);
+ int i;
+
+ ErrorF("Region num rects %d extents %d,%d %d,%d\n",nrects,
+ (REGION_EXTENTS(pScreen,reg))->x1,
+ (REGION_EXTENTS(pScreen,reg))->y1,
+ (REGION_EXTENTS(pScreen,reg))->x2,
+ (REGION_EXTENTS(pScreen,reg))->y2);
+
+ for (i = 0; i < nrects; i++) {
+ ErrorF(" rect %d,%d %dx%d\n",
+ REGION_RECTS(reg)[i].x1,
+ REGION_RECTS(reg)[i].y1,
+ REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1,
+ REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1);
+ }
+}
+#endif
+
+/**
+ * Allow scheduling updates from other functions in other files.
+ */
+void
+rfbScheduleUpdate(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ SCHEDULE_FB_UPDATE(pScreen, pVNC);
+}
--- xorg-server-1.7.4/hw/vnc/hextile.c
+++ xorg-server-1.7.4/hw/vnc/hextile.c
@@ -0,0 +1,350 @@
+/*
+ * hextile.c
+ *
+ * Routines to implement Hextile Encoding
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include "rfb.h"
+
+static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
+static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
+
+
+/*
+ * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
+ */
+
+Bool
+rfbSendRectEncodingHextile(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingHextile);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingHextile]++;
+ cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ return sendHextiles8(cl, x, y, w, h);
+ case 16:
+ return sendHextiles16(cl, x, y, w, h);
+ case 32:
+ return sendHextiles32(cl, x, y, w, h);
+ }
+
+ rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
+ return FALSE;
+}
+
+
+#define PUT_PIXEL8(pix) (pVNC->updateBuf[pVNC->ublen++] = (pix))
+
+#define PUT_PIXEL16(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \
+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1])
+
+#define PUT_PIXEL32(pix) (pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[0], \
+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[1], \
+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[2], \
+ pVNC->updateBuf[pVNC->ublen++] = ((char*)&(pix))[3])
+
+
+#define DEFINE_SEND_HEXTILES(bpp) \
+ \
+ \
+static Bool subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, \
+ int h, CARD##bpp bg, \
+ CARD##bpp fg, Bool mono); \
+static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \
+ Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \
+ \
+ \
+/* \
+ * rfbSendHextiles \
+ */ \
+ \
+static Bool \
+sendHextiles##bpp(cl, rx, ry, rw, rh) \
+ rfbClientPtr cl; \
+ int rx, ry, rw, rh; \
+{ \
+ VNCSCREENPTR(cl->pScreen); \
+ int x, y, w, h; \
+ int startUblen; \
+ CARD##bpp bg = 0, fg = 0, newBg, newFg; \
+ Bool mono, solid; \
+ Bool validBg = FALSE; \
+ Bool validFg = FALSE; \
+ CARD##bpp clientPixelData[16*16*(bpp/8)]; \
+ \
+ for (y = ry; y < ry+rh; y += 16) { \
+ for (x = rx; x < rx+rw; x += 16) { \
+ w = h = 16; \
+ if (rx+rw - x < 16) \
+ w = rx+rw - x; \
+ if (ry+rh - y < 16) \
+ h = ry+rh - y; \
+ \
+ if ((pVNC->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \
+ if (!rfbSendUpdateBuf(cl)) \
+ return FALSE; \
+ } \
+ \
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \
+ &pVNC->rfbServerFormat, \
+ &cl->format, (unsigned char *)clientPixelData, \
+ pVNC->paddedWidthInBytes, w, h, x, y); \
+ \
+ startUblen = pVNC->ublen; \
+ pVNC->updateBuf[startUblen] = 0; \
+ pVNC->ublen++; \
+ \
+ testColours##bpp(clientPixelData, w * h, \
+ &mono, &solid, &newBg, &newFg); \
+ \
+ if (!validBg || (newBg != bg)) { \
+ validBg = TRUE; \
+ bg = newBg; \
+ pVNC->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
+ PUT_PIXEL##bpp(bg); \
+ } \
+ \
+ if (solid) { \
+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \
+ continue; \
+ } \
+ \
+ pVNC->updateBuf[startUblen] |= rfbHextileAnySubrects; \
+ \
+ if (mono) { \
+ if (!validFg || (newFg != fg)) { \
+ validFg = TRUE; \
+ fg = newFg; \
+ pVNC->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
+ PUT_PIXEL##bpp(fg); \
+ } \
+ } else { \
+ validFg = FALSE; \
+ pVNC->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
+ } \
+ \
+ if (!subrectEncode##bpp(cl->pScreen, clientPixelData, w, h, bg, fg, mono)) { \
+ /* encoding was too large, use raw */ \
+ validBg = FALSE; \
+ validFg = FALSE; \
+ pVNC->ublen = startUblen; \
+ pVNC->updateBuf[pVNC->ublen++] = rfbHextileRaw; \
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, \
+ &pVNC->rfbServerFormat, &cl->format, \
+ (unsigned char *)clientPixelData, \
+ pVNC->paddedWidthInBytes, w, h, x, y); \
+ \
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)clientPixelData,\
+ w * h * (bpp/8)); \
+ \
+ pVNC->ublen += w * h * (bpp/8); \
+ } \
+ \
+ cl->rfbBytesSent[rfbEncodingHextile] += pVNC->ublen - startUblen; \
+ } \
+ } \
+ \
+ return TRUE; \
+} \
+ \
+ \
+static Bool \
+subrectEncode##bpp(ScreenPtr pScreen, CARD##bpp *data, int w, int h, \
+ CARD##bpp bg, CARD##bpp fg, Bool mono) \
+{ \
+ VNCSCREENPTR(pScreen); \
+ CARD##bpp clientdata; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ int nSubrectsUblen; \
+ \
+ nSubrectsUblen = pVNC->ublen; \
+ pVNC->ublen++; \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ clientdata = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != clientdata) {break;} \
+ i = x; \
+ while ((seg[i] == clientdata) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) { \
+ hy += 1; \
+ } else { \
+ hyflag = 0; \
+ } \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and \
+ * (x,y,vx,vy). We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ if (mono) { \
+ newLen = pVNC->ublen - nSubrectsUblen + 2; \
+ } else { \
+ newLen = pVNC->ublen - nSubrectsUblen + bpp/8 + 2; \
+ } \
+ \
+ if (newLen > (w * h * (bpp/8))) \
+ return FALSE; \
+ \
+ numsubs += 1; \
+ \
+ if (!mono) PUT_PIXEL##bpp(clientdata); \
+ \
+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackXY(thex,they); \
+ pVNC->updateBuf[pVNC->ublen++] = rfbHextilePackWH(thew,theh); \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ pVNC->updateBuf[nSubrectsUblen] = numsubs; \
+ \
+ return TRUE; \
+} \
+ \
+ \
+/* \
+ * testColours() tests if there are one (solid), two (mono) or more \
+ * colours in a tile and gets a reasonable guess at the best background \
+ * pixel, and the foreground pixel for mono. \
+ */ \
+ \
+static void \
+testColours##bpp(data,size,mono,solid,bg,fg) \
+ CARD##bpp *data; \
+ int size; \
+ Bool *mono; \
+ Bool *solid; \
+ CARD##bpp *bg; \
+ CARD##bpp *fg; \
+{ \
+ CARD##bpp colour1 = 0, colour2 = 0; \
+ int n1 = 0, n2 = 0; \
+ *mono = TRUE; \
+ *solid = TRUE; \
+ \
+ for (; size > 0; size--, data++) { \
+ \
+ if (n1 == 0) \
+ colour1 = *data; \
+ \
+ if (*data == colour1) { \
+ n1++; \
+ continue; \
+ } \
+ \
+ if (n2 == 0) { \
+ *solid = FALSE; \
+ colour2 = *data; \
+ } \
+ \
+ if (*data == colour2) { \
+ n2++; \
+ continue; \
+ } \
+ \
+ *mono = FALSE; \
+ break; \
+ } \
+ \
+ if (n1 > n2) { \
+ *bg = colour1; \
+ *fg = colour2; \
+ } else { \
+ *bg = colour2; \
+ *fg = colour1; \
+ } \
+}
+
+DEFINE_SEND_HEXTILES(8)
+DEFINE_SEND_HEXTILES(16)
+DEFINE_SEND_HEXTILES(32)
--- xorg-server-1.7.4/hw/vnc/httpd.c
+++ xorg-server-1.7.4/hw/vnc/httpd.c
@@ -0,0 +1,519 @@
+/*
+ * httpd.c - a simple HTTP server
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <pwd.h>
+#include <netdb.h>
+
+#ifndef USE_LIBWRAP
+#define USE_LIBWRAP 0
+#endif
+#if USE_LIBWRAP
+#include <tcpd.h>
+#endif
+
+#include "rfb.h"
+
+#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \
+ "<HEAD><TITLE>File Not Found</TITLE></HEAD>\n" \
+ "<BODY><H1>File Not Found</H1></BODY>\n"
+
+#define OK_STR "HTTP/1.0 200 OK\r\n\r\n"
+
+static void httpProcessInput(ScreenPtr pScreen);
+static Bool compareAndSkip(char **ptr, const char *str);
+static Bool parseParams(const char *request, char *result, int max_bytes);
+static Bool validateString(char *str);
+
+/*
+ * httpInitSockets sets up the TCP socket to listen for HTTP connections.
+ */
+
+Bool
+httpInitSockets(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+
+ if (!pVNC->httpDir)
+ return FALSE;
+
+ pVNC->buf_filled = 0;
+
+ if (pVNC->httpPort == 0) {
+ pVNC->httpPort = 5800 + atoi(display) + pScreen->myNum;
+ }
+
+ if ((pVNC->httpListenSock = ListenOnTCPPort(pScreen, pVNC->httpPort)) < 0) {
+ rfbLog("ListenOnTCPPort %d failed\n",pVNC->httpPort);
+ pVNC->httpPort = 0;
+ return FALSE;
+ }
+
+ rfbLog("Listening for HTTP connections on TCP port %d\n", pVNC->httpPort);
+ rfbLog(" URL http://%s:%d\n",rfbThisHost,pVNC->httpPort);
+
+ AddEnabledDevice(pVNC->httpListenSock);
+
+ return TRUE;
+}
+
+
+/*
+ * httpCheckFds is called from ProcessInputEvents to check for input on the
+ * HTTP socket(s). If there is input to process, httpProcessInput is called.
+ */
+
+void
+httpCheckFds(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ int nfds;
+ fd_set fds;
+ struct timeval tv;
+ struct sockaddr_in addr;
+ SOCKLEN_T addrlen = sizeof(addr);
+
+ if (!pVNC->httpDir)
+ return;
+
+ FD_ZERO(&fds);
+ FD_SET(pVNC->httpListenSock, &fds);
+ if (pVNC->httpSock >= 0) {
+ FD_SET(pVNC->httpSock, &fds);
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ nfds = select(max(pVNC->httpSock,pVNC->httpListenSock) + 1, &fds, NULL, NULL, &tv);
+ if (nfds == 0) {
+ return;
+ }
+ if (nfds < 0) {
+ if (errno != EINTR)
+ rfbLogPerror("httpCheckFds: select");
+ return;
+ }
+
+ if ((pVNC->httpSock >= 0) && FD_ISSET(pVNC->httpSock, &fds)) {
+ httpProcessInput(pScreen);
+ }
+
+ if (FD_ISSET(pVNC->httpListenSock, &fds)) {
+ int flags;
+
+ if (pVNC->httpSock >= 0) close(pVNC->httpSock);
+
+ if ((pVNC->httpSock = accept(pVNC->httpListenSock,
+ (struct sockaddr *)&addr, &addrlen)) < 0) {
+ rfbLogPerror("httpCheckFds: accept");
+ return;
+ }
+
+#if USE_LIBWRAP
+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr),
+ STRING_UNKNOWN)) {
+ rfbLog("Rejected HTTP connection from client %s\n",
+ inet_ntoa(addr.sin_addr));
+ close(pVNC->httpSock);
+ pVNC->httpSock = -1;
+ return;
+ }
+#endif
+
+ flags = fcntl (pVNC->httpSock, F_GETFL);
+
+ if (flags == -1 ||
+ fcntl (pVNC->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) {
+ rfbLogPerror("httpCheckFds: fcntl");
+ close (pVNC->httpSock);
+ pVNC->httpSock = -1;
+ return;
+ }
+
+ AddEnabledDevice(pVNC->httpSock);
+ }
+}
+
+
+static void
+httpCloseSock(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ close(pVNC->httpSock);
+ RemoveEnabledDevice(pVNC->httpSock);
+ pVNC->httpSock = -1;
+ pVNC->buf_filled = 0;
+}
+
+
+/*
+ * httpProcessInput is called when input is received on the HTTP socket.
+ */
+
+static void
+httpProcessInput(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ struct sockaddr_in addr;
+ SOCKLEN_T addrlen = sizeof(addr);
+ char fullFname[512];
+ char params[1024];
+ char *ptr;
+ char *fname;
+ int maxFnameLen;
+ int fd;
+ Bool performSubstitutions = FALSE;
+ char str[256];
+ struct passwd *user = getpwuid(getuid());
+
+ if (strlen(pVNC->httpDir) > 255) {
+ rfbLog("-httpd directory too long\n");
+ httpCloseSock(pScreen);
+ return;
+ }
+ strcpy(fullFname, pVNC->httpDir);
+ fname = &fullFname[strlen(fullFname)];
+ maxFnameLen = 511 - strlen(fullFname);
+
+ /* Read data from the HTTP client until we get a complete request. */
+ while (1) {
+ ssize_t got = read (pVNC->httpSock, pVNC->buf + pVNC->buf_filled,
+ sizeof (pVNC->buf) - pVNC->buf_filled - 1);
+
+ if (got <= 0) {
+ if (got == 0) {
+ rfbLog("httpd: premature connection close\n");
+ } else {
+ if (errno == EAGAIN) {
+ return;
+ }
+ rfbLogPerror("httpProcessInput: read");
+ }
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ pVNC->buf_filled += got;
+ pVNC->buf[pVNC->buf_filled] = '\0';
+
+ /* Is it complete yet (is there a blank line)? */
+ if (strstr (pVNC->buf, "\r\r") || strstr (pVNC->buf, "\n\n") ||
+ strstr (pVNC->buf, "\r\n\r\n") || strstr (pVNC->buf, "\n\r\n\r"))
+ break;
+ }
+
+ /* Process the request. */
+ if (strncmp(pVNC->buf, "GET ", 4)) {
+ rfbLog("httpd: no GET line\n");
+ httpCloseSock(pScreen);
+ return;
+ } else {
+ /* Only use the first line. */
+ pVNC->buf[strcspn(pVNC->buf, "\n\r")] = '\0';
+ }
+
+ if (strlen(pVNC->buf) > maxFnameLen) {
+ rfbLog("httpd: GET line too long\n");
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ if (sscanf(pVNC->buf, "GET %s HTTP/1.0", fname) != 1) {
+ rfbLog("httpd: couldn't parse GET line\n");
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ if (fname[0] != '/') {
+ rfbLog("httpd: filename didn't begin with '/'\n");
+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ if (strchr(fname+1, '/') != NULL) {
+ rfbLog("httpd: asking for file in other directory\n");
+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ getpeername(pVNC->httpSock, (struct sockaddr *)&addr, &addrlen);
+ rfbLog("httpd: get '%s' for %s\n", fname+1,
+ inet_ntoa(addr.sin_addr));
+
+ /* Extract parameters from the URL string if necessary */
+
+ params[0] = '\0';
+ ptr = strchr(fname, '?');
+ if (ptr != NULL) {
+ *ptr = '\0';
+ if (!parseParams(&ptr[1], params, 1024)) {
+ params[0] = '\0';
+ rfbLog("httpd: bad parameters in the URL\n");
+ }
+ }
+
+ /* If we were asked for '/', actually read the file index.vnc */
+
+ if (strcmp(fname, "/") == 0) {
+ strcpy(fname, "/index.vnc");
+ rfbLog("httpd: defaulting to '%s'\n", fname+1);
+ }
+
+ /* Substitutions are performed on files ending .vnc */
+
+ if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) {
+ performSubstitutions = TRUE;
+ }
+
+ /* Open the file */
+
+ if ((fd = open(fullFname, O_RDONLY)) < 0) {
+ rfbLogPerror("httpProcessInput: open");
+ WriteExact(pVNC->httpSock, NOT_FOUND_STR, strlen(NOT_FOUND_STR));
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ WriteExact(pVNC->httpSock, OK_STR, strlen(OK_STR));
+
+ while (1) {
+ int n = read(fd, pVNC->buf, HTTP_BUF_SIZE-1);
+ if (n < 0) {
+ rfbLogPerror("httpProcessInput: read");
+ close(fd);
+ httpCloseSock(pScreen);
+ return;
+ }
+
+ if (n == 0)
+ break;
+
+ if (performSubstitutions) {
+
+ /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values.
+ This won't quite work properly if the .vnc file is longer than
+ HTTP_BUF_SIZE, but it's reasonable to assume that .vnc files will
+ always be short. */
+
+ char *ptr = pVNC->buf;
+ char *dollar;
+ pVNC->buf[n] = 0; /* make sure it's null-terminated */
+
+ while ((dollar = strchr(ptr, '$'))) {
+ WriteExact(pVNC->httpSock, ptr, (dollar - ptr));
+
+ ptr = dollar;
+
+ if (compareAndSkip(&ptr, "$WIDTH")) {
+
+ sprintf(str, "%d", pVNC->width);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$HEIGHT")) {
+
+ sprintf(str, "%d", pVNC->height);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) {
+
+ sprintf(str, "%d", pVNC->width);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) {
+
+ sprintf(str, "%d", pVNC->height + 32);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$PORT")) {
+
+ sprintf(str, "%d", pVNC->rfbPort);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$DESKTOP")) {
+
+ WriteExact(pVNC->httpSock, desktopName, strlen(desktopName));
+
+ } else if (compareAndSkip(&ptr, "$DISPLAY")) {
+
+ sprintf(str, "%s:%s", rfbThisHost, display);
+ WriteExact(pVNC->httpSock, str, strlen(str));
+
+ } else if (compareAndSkip(&ptr, "$USER")) {
+
+ if (user) {
+ WriteExact(pVNC->httpSock, user->pw_name,
+ strlen(user->pw_name));
+ } else {
+ WriteExact(pVNC->httpSock, "?", 1);
+ }
+
+ } else if (compareAndSkip(&ptr, "$PARAMS")) {
+
+ if (params[0] != '\0')
+ WriteExact(pVNC->httpSock, params, strlen(params));
+
+ } else {
+ if (!compareAndSkip(&ptr, "$$"))
+ ptr++;
+
+ if (WriteExact(pVNC->httpSock, "$", 1) < 0) {
+ close(fd);
+ httpCloseSock(pScreen);
+ return;
+ }
+ }
+ }
+ if (WriteExact(pVNC->httpSock, ptr, (&pVNC->buf[n] - ptr)) < 0)
+ break;
+
+ } else {
+
+ /* For files not ending .vnc, just write out the buffer */
+
+ if (WriteExact(pVNC->httpSock, pVNC->buf, n) < 0)
+ break;
+ }
+ }
+
+ close(fd);
+ httpCloseSock(pScreen);
+}
+
+
+static Bool
+compareAndSkip(char **ptr, const char *str)
+{
+ if (strncmp(*ptr, str, strlen(str)) == 0) {
+ *ptr += strlen(str);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Parse the request tail after the '?' character, and format a sequence
+ * of <param> tags for inclusion into an HTML page with embedded applet.
+ */
+
+static Bool
+parseParams(const char *request, char *result, int max_bytes)
+{
+ char param_request[128];
+ char param_formatted[196];
+ const char *tail;
+ char *delim_ptr;
+ char *value_str;
+ int cur_bytes, len;
+
+ result[0] = '\0';
+ cur_bytes = 0;
+
+ tail = request;
+ for (;;) {
+ /* Copy individual "name=value" string into a buffer */
+ delim_ptr = strchr((char *)tail, '&');
+ if (delim_ptr == NULL) {
+ if (strlen(tail) >= sizeof(param_request)) {
+ return FALSE;
+ }
+ strcpy(param_request, tail);
+ } else {
+ len = delim_ptr - tail;
+ if (len >= sizeof(param_request)) {
+ return FALSE;
+ }
+ memcpy(param_request, tail, len);
+ param_request[len] = '\0';
+ }
+
+ /* Split the request into parameter name and value */
+ value_str = strchr(&param_request[1], '=');
+ if (value_str == NULL) {
+ return FALSE;
+ }
+ *value_str++ = '\0';
+ if (strlen(value_str) == 0) {
+ return FALSE;
+ }
+
+ /* Validate both parameter name and value */
+ if (!validateString(param_request) || !validateString(value_str)) {
+ return FALSE;
+ }
+
+ /* Prepare HTML-formatted representation of the name=value pair */
+ len = sprintf(param_formatted,
+ "<PARAM NAME=\"%s\" VALUE=\"%s\">\n",
+ param_request, value_str);
+ if (cur_bytes + len + 1 > max_bytes) {
+ return FALSE;
+ }
+ strcat(result, param_formatted);
+ cur_bytes += len;
+
+ /* Go to the next parameter */
+ if (delim_ptr == NULL) {
+ break;
+ }
+ tail = delim_ptr + 1;
+ }
+ return TRUE;
+}
+
+/*
+ * Check if the string consists only of alphanumeric characters, '+'
+ * signs, underscores, and dots. Replace all '+' signs with spaces.
+ */
+
+static Bool
+validateString(char *str)
+{
+ char *ptr;
+
+ for (ptr = str; *ptr != '\0'; ptr++) {
+ if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') {
+ if (*ptr == '+') {
+ *ptr = ' ';
+ } else {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
--- xorg-server-1.7.4/hw/vnc/init.c
+++ xorg-server-1.7.4/hw/vnc/init.c
@@ -0,0 +1,1078 @@
+/*
+ * init.c
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1993 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.
+
+*/
+
+/* Use ``#define CORBA'' to enable CORBA control interface */
+
+/* XXX this definition should probably go elsewhere */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef XVNCRELEASE
+#define XVNCRELEASE "X.org/xf4vnc custom version"
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include "X11/X.h"
+#define NEED_EVENTS
+#include "X11/Xproto.h"
+#include "X11/Xos.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#include "fb.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "dixstruct.h"
+#include <X11/Xatom.h>
+#include <errno.h>
+#include <sys/param.h>
+#include "dix.h"
+#include "micmap.h"
+#include "rfb.h"
+
+#ifdef CORBA
+#include <vncserverctrl.h>
+#endif
+
+#define RFB_DEFAULT_WIDTH 640
+#define RFB_DEFAULT_HEIGHT 480
+#define RFB_DEFAULT_DEPTH 8
+#define RFB_DEFAULT_WHITEPIXEL 0
+#define RFB_DEFAULT_BLACKPIXEL 1
+
+static unsigned long VNCGeneration = 0;
+rfbScreenInfo rfbScreen;
+extern char dispatchExceptionAtReset;
+
+extern void VncExtensionInit(void);
+
+static Bool initOutputCalled = FALSE;
+static Bool noCursor = FALSE;
+char *desktopName = "x11";
+
+char rfbThisHost[256];
+
+Atom VNC_LAST_CLIENT_ID;
+Atom VNC_CONNECT;
+
+#if 0
+static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 };
+static HWEventQueueType *mieqCheckForInput[2];
+#endif
+
+static char primaryOrder[4] = "";
+static int redBits, greenBits, blueBits;
+
+static Bool rfbScreenInit(int index, ScreenPtr pScreen, int argc,
+ char **argv);
+static int rfbKeybdProc(DeviceIntPtr pDevice, int onoff);
+static int rfbMouseProc(DeviceIntPtr pDevice, int onoff);
+static Bool CheckDisplayNumber(int n);
+
+static Bool rfbAlwaysTrue(void);
+static unsigned char *rfbAllocateFramebufferMemory(rfbScreenInfoPtr prfb);
+static Bool rfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y);
+static void rfbCrossScreen(ScreenPtr pScreen, Bool entering);
+
+
+
+static void
+PointerWarpCursor(ScreenPtr pScreen, int x, int y)
+{
+#if 0
+ DeviceIntPtr pDev = NULL;
+ miPointerSetPosition(pDev, &x, &y, GetTimeInMillis());
+#endif
+}
+
+
+static miPointerScreenFuncRec rfbPointerCursorFuncs = {
+ rfbCursorOffScreen,
+ rfbCrossScreen,
+ PointerWarpCursor,
+ NULL/*dmxeqEnqueue*/,
+ NULL/*dmxeqSwitchScreen*/
+};
+
+
+int inetdSock = -1;
+static char inetdDisplayNumStr[10];
+
+
+void
+DDXRingBell(int volume, int pitch, int duration)
+{
+ /* NO-OP - stub to solve link problem */
+}
+
+
+/*
+ * ddxProcessArgument is our first entry point and will be called at the
+ * very start for each argument. It is not called again on server reset.
+ */
+
+int
+ddxProcessArgument (argc, argv, i)
+ int argc;
+ char *argv[];
+ int i;
+{
+ VNCSCREENPTR(screenInfo.screens[i]);
+ static Bool firstTime = TRUE;
+
+ if (firstTime)
+ {
+ pVNC->width = RFB_DEFAULT_WIDTH;
+ pVNC->height = RFB_DEFAULT_HEIGHT;
+ pVNC->depth = RFB_DEFAULT_DEPTH;
+ pVNC->blackPixel = RFB_DEFAULT_BLACKPIXEL;
+ pVNC->whitePixel = RFB_DEFAULT_WHITEPIXEL;
+ pVNC->pfbMemory = NULL;
+ pVNC->httpPort = 0;
+ pVNC->httpDir = NULL;
+ pVNC->rfbAuthPasswdFile = NULL;
+ pVNC->udpPort = 0;
+ pVNC->rfbPort = 0;
+ pVNC->rdpPort = 3389;
+ noCursor = FALSE;
+ pVNC->loginAuthEnabled = FALSE;
+ pVNC->rfbAlwaysShared = FALSE;
+ pVNC->rfbNeverShared = FALSE;
+ pVNC->rfbDontDisconnect = FALSE;
+ pVNC->rfbViewOnly = FALSE;
+
+ gethostname(rfbThisHost, 255);
+ pVNC->interface.s_addr = htonl (INADDR_ANY);
+ firstTime = FALSE;
+ }
+
+ if (strcmp (argv[i], "-geometry") == 0) /* -geometry WxH */
+ {
+ if (i + 1 >= argc) UseMsg();
+ if (sscanf(argv[i+1],"%dx%d",
+ &pVNC->width,&pVNC->height) != 2) {
+ ErrorF("Invalid geometry %s\n", argv[i+1]);
+ UseMsg();
+ }
+#ifdef CORBA
+ screenWidth= pVNC->width;
+ screenHeight= pVNC->height;
+#endif
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-depth") == 0) /* -depth D */
+ {
+ if (i + 1 >= argc) UseMsg();
+ pVNC->depth = atoi(argv[i+1]);
+#ifdef CORBA
+ screenDepth= pVNC->depth;
+#endif
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-pixelformat") == 0) {
+ if (i + 1 >= argc) UseMsg();
+ if (sscanf(argv[i+1], "%3s", primaryOrder) < 1) {
+ ErrorF("Invalid pixel format %s\n", argv[i+1]);
+ UseMsg();
+ }
+
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-blackpixel") == 0) { /* -blackpixel n */
+ if (i + 1 >= argc) UseMsg();
+ pVNC->blackPixel = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-whitepixel") == 0) { /* -whitepixel n */
+ if (i + 1 >= argc) UseMsg();
+ pVNC->whitePixel = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-udpinputport") == 0) { /* -udpinputport port */
+ if (i + 1 >= argc) UseMsg();
+ pVNC->udpPort = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
+ if (i + 1 >= argc) UseMsg();
+ pVNC->rfbPort = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
+ if (i + 1 >= argc) UseMsg();
+ rfbMaxClientWait = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-nocursor") == 0) {
+ noCursor = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
+ if (i + 1 >= argc) UseMsg();
+ pVNC->rfbAuthPasswdFile = argv[i+1];
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-loginauth") == 0) {
+ if (geteuid() == 0) {
+ /* Only when run as root! */
+ pVNC->loginAuthEnabled = TRUE;
+ }
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-httpd") == 0) {
+ if (i + 1 >= argc) UseMsg();
+ pVNC->httpDir = argv[i+1];
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-httpport") == 0) {
+ if (i + 1 >= argc) UseMsg();
+ pVNC->httpPort = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate ms */
+ if (i + 1 >= argc) UseMsg();
+ rfbDeferUpdateTime = atoi(argv[i+1]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-economictranslate") == 0) {
+ rfbEconomicTranslate = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-lazytight") == 0) {
+ rfbTightDisableGradient = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
+ if (i + 1 >= argc) UseMsg();
+ desktopName = argv[i+1];
+ return 2;
+ }
+
+#if 0 /* not deemed useful on standalone server - leave for completeness */
+ if (strcmp(argv[i], "-useraccept") == 0) {
+ pVNC->rfbUserAccept = TRUE;
+ return 1;
+ }
+#endif
+
+ if (strcmp(argv[i], "-alwaysshared") == 0) {
+ pVNC->rfbAlwaysShared = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-nevershared") == 0) {
+ pVNC->rfbNeverShared = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-dontdisconnect") == 0) {
+ pVNC->rfbDontDisconnect = TRUE;
+ return 1;
+ }
+
+ /* Run server in view-only mode - Ehud Karni SW */
+ if (strcmp(argv[i], "-viewonly") == 0) {
+ pVNC->rfbViewOnly = TRUE;
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-localhost") == 0) {
+ pVNC->interface.s_addr = htonl (INADDR_LOOPBACK);
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-interface") == 0) { /* -interface ipaddr */
+ struct in_addr got;
+ unsigned long octet;
+ char *p, *end;
+ int q;
+ got.s_addr = 0;
+ if (i + 1 >= argc) {
+ UseMsg();
+ return 2;
+ }
+ if (pVNC->interface.s_addr != htonl (INADDR_ANY)) {
+ /* Already set (-localhost?). */
+ return 2;
+ }
+ p = argv[i + 1];
+ for (q = 0; q < 4; q++) {
+ octet = strtoul (p, &end, 10);
+ if (p == end || octet > 255) {
+ UseMsg ();
+ return 2;
+ }
+ if ((q < 3 && *end != '.') ||
+ (q == 3 && *end != '\0')) {
+ UseMsg ();
+ return 2;
+ }
+ got.s_addr = (got.s_addr << 8) | octet;
+ p = end + 1;
+ }
+ pVNC->interface.s_addr = htonl (got.s_addr);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-inetd") == 0) { /* -inetd */
+ int n;
+ for (n = 1; n < 100; n++) {
+ if (CheckDisplayNumber(n))
+ break;
+ }
+
+ if (n >= 100)
+ FatalError("-inetd: couldn't find free display number");
+
+ sprintf(inetdDisplayNumStr, "%d", n);
+ display = inetdDisplayNumStr;
+
+ /* fds 0, 1 and 2 (stdin, out and err) are all the same socket to the
+ RFB client. OsInit() closes stdout and stdin, and we don't want
+ stderr to go to the RFB client, so make the client socket 3 and
+ close stderr. OsInit() will redirect stderr logging to an
+ appropriate log file or /dev/null if that doesn't work. */
+
+ dup2(0,3);
+ inetdSock = 3;
+ close(2);
+
+ return 1;
+ }
+
+ if (strcmp(argv[i], "-version") == 0) {
+ ErrorF("Xvnc version %s\n", XVNCRELEASE);
+ exit(0);
+ }
+
+ if (inetdSock != -1 && argv[i][0] == ':') {
+ FatalError("can't specify both -inetd and :displaynumber");
+ }
+
+ return 0;
+}
+
+
+/*
+ * InitOutput is called every time the server resets. It should call
+ * AddScreen for each screen (FIXME - but we only ever have one),
+ * and in turn this will call rfbScreenInit.
+ */
+
+/* Common pixmap formats */
+
+static PixmapFormatRec formats[MAXFORMATS] = {
+ { 1, 1, BITMAP_SCANLINE_PAD },
+ { 4, 8, BITMAP_SCANLINE_PAD },
+ { 8, 8, BITMAP_SCANLINE_PAD },
+ { 15, 16, BITMAP_SCANLINE_PAD },
+ { 16, 16, BITMAP_SCANLINE_PAD },
+ { 24, 32, BITMAP_SCANLINE_PAD },
+#ifdef RENDER
+ { 32, 32, BITMAP_SCANLINE_PAD },
+#endif
+};
+#ifdef RENDER
+static int numFormats = 7;
+#else
+static int numFormats = 6;
+#endif
+
+void
+InitOutput(screenInfo, argc, argv)
+ ScreenInfo *screenInfo;
+ int argc;
+ char **argv;
+{
+ int i;
+ initOutputCalled = TRUE;
+
+ rfbLog("Xvnc version %s\n", XVNCRELEASE);
+ rfbLog("Copyright (C) 2001-2004 Alan Hourihane.\n");
+ rfbLog("Copyright (C) 2000-2004 Constantin Kaplinsky\n");
+ rfbLog("Copyright (C) 1999 AT&T Laboratories Cambridge\n");
+ rfbLog("All Rights Reserved.\n");
+ rfbLog("See http://www.tightvnc.com/ for information on TightVNC\n");
+ rfbLog("See http://xf4vnc.sf.net for xf4vnc-specific information\n");
+ rfbLog("Desktop name '%s' (%s:%s)\n",desktopName,rfbThisHost,display);
+ rfbLog("Protocol versions supported: %d.%d, %d.%d\n",
+ rfbProtocolMajorVersion, rfbProtocolMinorVersion,
+ rfbProtocolMajorVersion, rfbProtocolFallbackMinorVersion);
+
+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID",
+ strlen("VNC_LAST_CLIENT_ID"), TRUE);
+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE);
+
+ /* initialize pixmap formats */
+
+ screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ screenInfo->numPixmapFormats = numFormats;
+ for (i = 0; i < numFormats; i++)
+ screenInfo->formats[i] = formats[i];
+
+ /* initialize screen */
+
+ if (AddScreen(rfbScreenInit, argc, argv) == -1) {
+ FatalError("Couldn't add screen");
+ }
+
+#ifdef CORBA
+ initialiseCORBA(argc, argv, desktopName);
+#endif
+}
+
+static void
+rfbWakeupHandler (
+ int i,
+ pointer blockData,
+ unsigned long err,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ VNCSCREENPTR(pScreen);
+ int e = (int)err;
+
+ if (e < 0)
+ goto SKIPME;
+
+ rfbRootPropertyChange(pScreen);
+
+#if XFREE86VNC
+ if (pScrn->vtSema) {
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+#if 0
+ rdpCheckFds(pScreen);
+#endif
+#ifdef CORBA
+ corbaCheckFds();
+#endif
+ } else {
+ rfbCheckFds(pScreen);
+#if 0
+ rdpCheckFds(pScreen);
+#endif
+ }
+#else
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+#if 0
+ rdpCheckFds(pScreen);
+#endif
+#ifdef CORBA
+ corbaCheckFds();
+#endif
+#endif
+
+SKIPME:
+
+ pScreen->WakeupHandler = pVNC->WakeupHandler;
+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask);
+ pScreen->WakeupHandler = rfbWakeupHandler;
+}
+
+static Bool
+rfbScreenInit(index, pScreen, argc, argv)
+ int index;
+ ScreenPtr pScreen;
+ int argc;
+ char ** argv;
+{
+ rfbScreenInfoPtr prfb = &rfbScreen;
+ int dpix = 75, dpiy = 75;
+ int ret;
+ unsigned char *pbits;
+ VisualPtr vis;
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
+
+ if (VNCGeneration != serverGeneration) {
+ VncExtensionInit();
+ VNCGeneration = serverGeneration;
+ }
+
+ if (monitorResolution != 0) {
+ dpix = monitorResolution;
+ dpiy = monitorResolution;
+ }
+
+ prfb->rfbAuthTries = 0;
+ prfb->rfbAuthTooManyTries = FALSE;
+ prfb->rfbUserAccept = FALSE;
+ prfb->udpSockConnected = FALSE;
+ prfb->timer = NULL;
+ prfb->httpListenSock = -1;
+ prfb->httpSock = -1;
+ prfb->rfbListenSock = -1;
+ prfb->rdpListenSock = -1;
+ prfb->paddedWidthInBytes = PixmapBytePad(prfb->width, prfb->depth);
+ prfb->bitsPerPixel = rfbBitsPerPixel(prfb->depth);
+ pbits = rfbAllocateFramebufferMemory(prfb);
+ if (!pbits) return FALSE;
+
+ miClearVisualTypes();
+
+ if (defaultColorVisualClass == -1)
+ defaultColorVisualClass = TrueColor;
+
+ if (!miSetVisualTypes(prfb->depth, miGetDefaultVisualMask(prfb->depth), 8,
+ defaultColorVisualClass) )
+ return FALSE;
+
+ miSetPixmapDepths();
+
+ switch (prfb->bitsPerPixel)
+ {
+ case 8:
+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height,
+ dpix, dpiy, prfb->paddedWidthInBytes, 8);
+ break;
+ case 16:
+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height,
+ dpix, dpiy, prfb->paddedWidthInBytes / 2, 16);
+ if (prfb->depth == 15) {
+ blueBits = 5; greenBits = 5; redBits = 5;
+ } else {
+ blueBits = 5; greenBits = 6; redBits = 5;
+ }
+ break;
+ case 32:
+ ret = fbScreenInit(pScreen, pbits, prfb->width, prfb->height,
+ dpix, dpiy, prfb->paddedWidthInBytes / 4, 32);
+ blueBits = 8; greenBits = 8; redBits = 8;
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (!ret) return FALSE;
+
+ miInitializeBackingStore(pScreen);
+
+ if (prfb->bitsPerPixel > 8) {
+ if (strcasecmp(primaryOrder, "bgr") == 0) {
+ rfbLog("BGR format %d %d %d\n", blueBits, greenBits, redBits);
+ vis = pScreen->visuals + pScreen->numVisuals;
+ while (--vis >= pScreen->visuals) {
+ if ((vis->class | DynamicClass) == DirectColor) {
+ vis->offsetRed = 0;
+ vis->redMask = (1 << redBits) - 1;
+ vis->offsetGreen = redBits;
+ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
+ vis->offsetBlue = redBits + greenBits;
+ vis->blueMask = ((1 << blueBits) - 1) << vis->offsetBlue;
+ }
+ }
+ } else {
+ rfbLog("RGB format %d %d %d\n", blueBits, greenBits, redBits);
+ vis = pScreen->visuals + pScreen->numVisuals;
+ while (--vis >= pScreen->visuals) {
+ if ((vis->class | DynamicClass) == DirectColor) {
+ vis->offsetBlue = 0;
+ vis->blueMask = (1 << blueBits) - 1;
+ vis->offsetGreen = blueBits;
+ vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
+ vis->offsetRed = blueBits + greenBits;
+ vis->redMask = ((1 << redBits) - 1) << vis->offsetRed;
+ }
+ }
+ }
+ }
+
+ if (prfb->bitsPerPixel > 4)
+ fbPictureInit(pScreen, 0, 0);
+
+ prfb->cursorIsDrawn = FALSE;
+ prfb->dontSendFramebufferUpdate = FALSE;
+
+ prfb->CloseScreen = pScreen->CloseScreen;
+ prfb->WakeupHandler = pScreen->WakeupHandler;
+ prfb->CreateGC = pScreen->CreateGC;
+ prfb->PaintWindowBackground = pScreen->PaintWindowBackground;
+ prfb->PaintWindowBorder = pScreen->PaintWindowBorder;
+ prfb->CopyWindow = pScreen->CopyWindow;
+ prfb->ClearToBackground = pScreen->ClearToBackground;
+ prfb->RestoreAreas = pScreen->RestoreAreas;
+#ifdef CHROMIUM
+ prfb->RealizeWindow = pScreen->RealizeWindow;
+ prfb->UnrealizeWindow = pScreen->UnrealizeWindow;
+ prfb->DestroyWindow = pScreen->DestroyWindow;
+ prfb->PositionWindow = pScreen->PositionWindow;
+ prfb->ResizeWindow = pScreen->ResizeWindow;
+ prfb->ClipNotify = pScreen->ClipNotify;
+#endif
+#ifdef RENDER
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ prfb->Composite = ps->Composite;
+#endif
+ pScreen->CloseScreen = rfbCloseScreen;
+ pScreen->WakeupHandler = rfbWakeupHandler;
+ pScreen->CreateGC = rfbCreateGC;
+ pScreen->PaintWindowBackground = rfbPaintWindowBackground;
+ pScreen->PaintWindowBorder = rfbPaintWindowBorder;
+ pScreen->CopyWindow = rfbCopyWindow;
+ pScreen->ClearToBackground = rfbClearToBackground;
+ pScreen->RestoreAreas = rfbRestoreAreas;
+#ifdef CHROMIUM
+ pScreen->RealizeWindow = rfbRealizeWindow;
+ pScreen->UnrealizeWindow = rfbUnrealizeWindow;
+ pScreen->DestroyWindow = rfbDestroyWindow;
+ pScreen->PositionWindow = rfbPositionWindow;
+ pScreen->ResizeWindow = rfbResizeWindow;
+ pScreen->ClipNotify = rfbClipNotify;
+#endif
+#ifdef RENDER
+ if (ps)
+ ps->Composite = rfbComposite;
+#endif
+
+ pScreen->InstallColormap = rfbInstallColormap;
+ pScreen->UninstallColormap = rfbUninstallColormap;
+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
+ pScreen->StoreColors = rfbStoreColors;
+
+ pScreen->SaveScreen = (SaveScreenProcPtr)rfbAlwaysTrue;
+
+ rfbDCInitialize(pScreen, &rfbPointerCursorFuncs);
+
+ if (noCursor) {
+ pScreen->DisplayCursor = (DisplayCursorProcPtr)rfbAlwaysTrue;
+ prfb->cursorIsDrawn = TRUE;
+ }
+
+ pScreen->blackPixel = prfb->blackPixel;
+ pScreen->whitePixel = prfb->whitePixel;
+
+ prfb->rfbServerFormat.bitsPerPixel = prfb->bitsPerPixel;
+ prfb->rfbServerFormat.depth = prfb->depth;
+ prfb->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
+
+ /* Find the root visual and set the server format */
+ for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
+ ;
+ prfb->rfbServerFormat.trueColour = (vis->class == TrueColor);
+
+ if ( (vis->class == TrueColor) || (vis->class == DirectColor) ) {
+ prfb->rfbServerFormat.redMax = vis->redMask >> vis->offsetRed;
+ prfb->rfbServerFormat.greenMax = vis->greenMask >> vis->offsetGreen;
+ prfb->rfbServerFormat.blueMax = vis->blueMask >> vis->offsetBlue;
+ prfb->rfbServerFormat.redShift = vis->offsetRed;
+ prfb->rfbServerFormat.greenShift = vis->offsetGreen;
+ prfb->rfbServerFormat.blueShift = vis->offsetBlue;
+ } else {
+ prfb->rfbServerFormat.redMax
+ = prfb->rfbServerFormat.greenMax
+ = prfb->rfbServerFormat.blueMax = 0;
+ prfb->rfbServerFormat.redShift
+ = prfb->rfbServerFormat.greenShift
+ = prfb->rfbServerFormat.blueShift = 0;
+ }
+
+ ret = fbCreateDefColormap(pScreen);
+
+ rfbInitSockets(pScreen);
+#if 0
+ rdpInitSockets(pScreen);
+#endif
+ if (inetdSock == -1)
+ httpInitSockets(pScreen);
+
+ return ret;
+
+} /* end rfbScreenInit */
+
+
+
+/*
+ * InitInput is also called every time the server resets. It is called after
+ * InitOutput so we can assume that rfbInitSockets has already been called.
+ */
+void
+InitInput(argc, argv)
+ int argc;
+ char *argv[];
+{
+ DeviceIntPtr p, k;
+ k = AddInputDevice(rfbKeybdProc, TRUE);
+ p = AddInputDevice(rfbMouseProc, TRUE);
+ RegisterKeyboardDevice(k);
+ RegisterPointerDevice(p);
+
+ mieqInit();
+
+#if 0
+ mieqCheckForInput[0] = checkForInput[0];
+ mieqCheckForInput[1] = checkForInput[1];
+ SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
+#endif
+}
+
+
+static int
+rfbKeybdProc(pDevice, onoff)
+ DeviceIntPtr pDevice;
+ int onoff;
+{
+ KeySymsRec keySyms;
+ CARD8 modMap[MAP_LENGTH];
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ vncSetKeyboardDevice(pDevice);
+ KbdDeviceInit(pDevice, &keySyms, modMap);
+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+ (BellProcPtr)rfbSendBell,
+ (KbdCtrlProcPtr)NoopDDA);
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ KbdDeviceOn();
+ break;
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ KbdDeviceOff();
+ break;
+ case DEVICE_CLOSE:
+ vncSetKeyboardDevice(NULL);
+ if (pDev->on)
+ KbdDeviceOff();
+ break;
+ }
+ return Success;
+}
+
+static int
+rfbMouseProc(pDevice, onoff)
+ DeviceIntPtr pDevice;
+ int onoff;
+{
+ BYTE map[6];
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ PtrDeviceInit();
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ map[4] = 4;
+ map[5] = 5;
+ InitPointerDeviceStruct(pDev, map, 5,
+ GetMotionHistory,
+ PtrDeviceControl,
+ GetMaximumEventsNum(), 2 /* numAxes */);
+ vncSetPointerDevice(pDevice);
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ PtrDeviceOn(pDevice);
+ break;
+
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ PtrDeviceOff();
+ break;
+
+ case DEVICE_CLOSE:
+ vncSetPointerDevice(NULL);
+ if (pDev->on)
+ PtrDeviceOff();
+ break;
+ }
+ return Success;
+}
+
+
+Bool
+LegalModifier(unsigned int key, DeviceIntPtr pDev)
+{
+ return TRUE;
+}
+
+
+void
+ProcessInputEvents(void)
+{
+#if 0
+ if (*mieqCheckForInput[0] != *mieqCheckForInput[1]) {
+#endif
+ mieqProcessInputEvents();
+#if 0
+ }
+#endif
+}
+
+
+static Bool CheckDisplayNumber(int n)
+{
+ char fname[32];
+ int sock;
+ struct sockaddr_in addr;
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(6000+n);
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(sock);
+ return FALSE;
+ }
+ close(sock);
+
+ sprintf(fname, "/tmp/.X%d-lock", n);
+ if (access(fname, F_OK) == 0)
+ return FALSE;
+
+ sprintf(fname, "/tmp/.X11-unix/X%d", n);
+ if (access(fname, F_OK) == 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+static Bool
+rfbAlwaysTrue(void)
+{
+ return TRUE;
+}
+
+
+static unsigned char *
+rfbAllocateFramebufferMemory(prfb)
+ rfbScreenInfoPtr prfb;
+{
+ if (prfb->pfbMemory) return prfb->pfbMemory; /* already done */
+
+ prfb->sizeInBytes = (prfb->paddedWidthInBytes * prfb->height);
+
+ prfb->pfbMemory = (unsigned char *)Xalloc(prfb->sizeInBytes);
+
+ return prfb->pfbMemory;
+}
+
+
+static Bool
+rfbCursorOffScreen (ppScreen, x, y)
+ ScreenPtr *ppScreen;
+ int *x, *y;
+{
+ return FALSE;
+}
+
+static void
+rfbCrossScreen (pScreen, entering)
+ ScreenPtr pScreen;
+ Bool entering;
+{
+}
+
+void
+ddxGiveUp()
+{
+ Xfree(rfbScreen.pfbMemory);
+ if (initOutputCalled) {
+ char unixSocketName[32];
+ sprintf(unixSocketName,"/tmp/.X11-unix/X%s",display);
+ unlink(unixSocketName);
+#ifdef CORBA
+ shutdownCORBA();
+#endif
+ }
+}
+
+void
+AbortDDX()
+{
+ ddxGiveUp();
+}
+
+void
+OsVendorInit()
+{
+}
+
+void
+OsVendorFatalError()
+{
+}
+
+#ifdef DDXTIME /* from ServerOSDefines */
+CARD32
+GetTimeInMillis()
+{
+ struct timeval tp;
+
+ X_GETTIMEOFDAY(&tp);
+ return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+#endif
+
+void
+ddxUseMsg()
+{
+ ErrorF("-geometry WxH set framebuffer width & height\n");
+ ErrorF("-depth D set framebuffer depth\n");
+ ErrorF("-pixelformat format set pixel format (BGRnnn or RGBnnn)\n");
+ ErrorF("-udpinputport port UDP port for keyboard/pointer data\n");
+ ErrorF("-rfbport port TCP port for RFB protocol\n");
+ ErrorF("-rfbwait time max time in ms to wait for RFB client\n");
+ ErrorF("-nocursor don't put up a cursor\n");
+ ErrorF("-rfbauth passwd-file use authentication on RFB protocol\n");
+ ErrorF("-loginauth use login-style Unix authentication\n");
+ ErrorF("-httpd dir serve files via HTTP from here\n");
+ ErrorF("-httpport port port for HTTP\n");
+ ErrorF("-deferupdate time time in ms to defer updates "
+ "(default 40)\n");
+ ErrorF("-economictranslate less memory-hungry translation\n");
+ ErrorF("-lazytight disable \"gradient\" filter in tight "
+ "encoding\n");
+ ErrorF("-desktop name VNC desktop name (default x11)\n");
+ ErrorF("-alwaysshared always treat new clients as shared\n");
+ ErrorF("-nevershared never treat new clients as shared\n");
+ ErrorF("-dontdisconnect don't disconnect existing clients when a "
+ "new non-shared\n"
+ " connection comes in (refuse new connection "
+ "instead)\n");
+ ErrorF("-localhost only allow connections from localhost\n"
+ " to the vnc ports. Use -nolisten tcp to disable\n"
+ " remote X clients as well.\n");
+ ErrorF("-viewonly let clients only view the desktop\n");
+ ErrorF("-interface ipaddr only bind to specified interface "
+ "address\n");
+ ErrorF("-inetd Xvnc is launched by inetd\n");
+ exit(1);
+}
+
+
+void ddxInitGlobals(void)
+{
+ /* dummy function called by InitGlobals in os/utils.c */
+}
+
+int
+NewInputDeviceRequest(InputOption *options, DeviceIntPtr *pdev)
+{
+ return BadValue;
+}
+
+void
+DeleteInputDeviceRequest(DeviceIntPtr dev)
+{
+}
+
+
+/*
+ * rfbLog prints a time-stamped message to the log file (stderr).
+ */
+
+void rfbLog(char *format, ...)
+{
+ va_list args;
+ char buf[256];
+ time_t clock;
+
+ va_start(args, format);
+
+ time(&clock);
+ strftime(buf, 255, "%d/%m/%Y %H:%M:%S ", localtime(&clock));
+ fprintf(stderr, buf);
+
+ vfprintf(stderr, format, args);
+ fflush(stderr);
+
+ va_end(args);
+}
+
+void rfbLogPerror(char *str)
+{
+ rfbLog("");
+ perror(str);
+}
--- xorg-server-1.7.4/hw/vnc/kbdptr.c
+++ xorg-server-1.7.4/hw/vnc/kbdptr.c
@@ -0,0 +1,458 @@
+/*
+ * kbdptr.c - deal with keyboard and pointer device over TCP & UDP.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include "rfb.h"
+#include "X11/X.h"
+#define NEED_EVENTS
+#include "X11/Xproto.h"
+#include "inputstr.h"
+#define XK_CYRILLIC
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include "mi.h"
+#include "mipointer.h"
+#include "keyboard.h"
+
+#ifdef DMXVNC
+#include "dmxinput.h"
+#endif
+
+#define KEY_IS_PRESSED(keycode) \
+ (kbdDevice->key->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
+
+static void vncXConvertCase(KeySym sym, KeySym *lower, KeySym *upper);
+
+static DeviceIntPtr ptrDevice = NULL, kbdDevice = NULL;
+
+
+void
+vncSetKeyboardDevice(DeviceIntPtr kbd)
+{
+ if (kbdDevice && kbd)
+ return; /* set once */
+ kbdDevice = kbd;
+}
+
+
+void
+vncSetPointerDevice(DeviceIntPtr ptr)
+{
+ if (ptrDevice && ptr)
+ return; /* set once */
+ ptrDevice = ptr;
+}
+
+
+#ifndef DMXVNC
+static void
+EnqueueMotion(DeviceIntPtr ptrDev, int x, int y)
+{
+ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum());
+ int detail = 0, valuators[2], nevents, i;
+ valuators[0] = x;
+ valuators[1] = y;
+ if (!ptrDev) {
+ ErrorF("VNC: In EnqueueMotion() ptrDev=NULL\n");
+ return;
+ }
+ nevents = GetPointerEvents(events, ptrDev, MotionNotify, detail,
+ POINTER_ABSOLUTE, 0, 2, valuators);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(ptrDev, events + i);
+ free(events);
+}
+#endif
+
+
+static void
+EnqueueButton(DeviceIntPtr ptrDev, int type, int detail)
+{
+ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum());
+ int nevents, i;
+ if (!ptrDev) {
+ ErrorF("VNC: In EnqueueButton() ptrDev=NULL\n");
+ return;
+ }
+ nevents = GetPointerEvents(events, ptrDev, type, detail,
+ POINTER_ABSOLUTE, 0, 0, NULL/*valuators*/);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(ptrDev, events + i);
+ free(events);
+}
+
+
+static void
+EnqueueKey(DeviceIntPtr kbdDev, int type, int detail)
+{
+ xEvent *events = (xEvent*) calloc(sizeof(xEvent), GetMaximumEventsNum());
+ int nevents, i;
+ if (!kbdDev) {
+ ErrorF("VNC: In EnqueueKey() kbdDev=NULL\n");
+ return;
+ }
+ nevents = GetKeyboardEvents(events, kbdDev, type, detail);
+ for (i = 0; i < nevents; i++)
+ mieqEnqueue(kbdDev, events + i);
+ free(events);
+}
+
+
+/*
+ * Called when the rfbserver receives a rfbKeyEvent event from a client.
+ * Put an X keyboard event into the event queue.
+ */
+void
+KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl)
+{
+ const int type = down ? KeyPress : KeyRelease;
+ KeySymsPtr keySyms;
+ int i;
+ int keyCode = 0;
+ int freeIndex = -1;
+ Bool fakeShiftPress = FALSE;
+ Bool fakeShiftLRelease = FALSE;
+ Bool fakeShiftRRelease = FALSE;
+ Bool shiftMustBeReleased = FALSE;
+ Bool shiftMustBePressed = FALSE;
+
+ if (!kbdDevice)
+ return;
+
+ keySyms = &kbdDevice->key->curKeySyms;
+
+#ifdef CORBA
+ if (cl) {
+ CARD32 clientId = cl->sock;
+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER,
+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE);
+ }
+#endif
+
+ /* NOTE: This is where it gets hairy for XFree86 servers.
+ * I think the best way to deal with this is invent a new protocol
+ * to send over the wire the remote keyboard type and correctly
+ * handle that as XINPUT extension device (we're part of the way
+ * there for that.
+ *
+ * Alan.
+ */
+#if !XFREE86VNC
+ /* First check if it's one of our predefined keys. If so then we can make
+ some attempt at allowing an xmodmap inside a VNC desktop behave
+ something like you'd expect - e.g. if keys A & B are swapped over and
+ the VNC client sends an A, then map it to a B when generating the X
+ event. We don't attempt to do this for keycodes which we make up on the
+ fly because it's too hard... */
+
+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) {
+ if (keySym == map[i]) {
+ keyCode = MIN_KEY_CODE + i / GLYPHS_PER_KEY;
+
+ if (map[(i/GLYPHS_PER_KEY) * GLYPHS_PER_KEY + 1] != NoSymbol) {
+
+ /* this keycode has more than one symbol associated with it,
+ so shift state is important */
+
+ if ((i % GLYPHS_PER_KEY) == 0)
+ shiftMustBeReleased = TRUE;
+ else
+ shiftMustBePressed = TRUE;
+ }
+ break;
+ }
+ }
+#endif
+
+ if (!keyCode) {
+
+ /* not one of our predefined keys - see if it's in the current keyboard
+ mapping (i.e. we've already allocated an extra keycode for it) */
+
+ if (keySyms->mapWidth < 2) {
+ ErrorF("KbdAddEvent: Sanity check failed - Keyboard mapping has "
+ "less than 2 keysyms per keycode (KeySym 0x%x)\n", (int)keySym);
+ return;
+ }
+
+ for (i = 0; i < NO_OF_KEYS * keySyms->mapWidth; i++) {
+ if (keySym == keySyms->map[i]) {
+ keyCode = MIN_KEY_CODE + i / keySyms->mapWidth;
+
+ if (keySyms->map[(i / keySyms->mapWidth)
+ * keySyms->mapWidth + 1] != NoSymbol) {
+
+ /* this keycode has more than one symbol associated with
+ it, so shift state is important */
+
+ if ((i % keySyms->mapWidth) == 0)
+ shiftMustBeReleased = TRUE;
+ else
+ shiftMustBePressed = TRUE;
+ }
+ break;
+ }
+ if ((freeIndex == -1) && (keySyms->map[i] == NoSymbol)
+ && (i % keySyms->mapWidth) == 0)
+ {
+ freeIndex = i;
+ }
+ }
+ }
+
+ if (!keyCode) {
+ KeySym lower, upper;
+
+ /* we don't have an existing keycode - make one up on the fly and add
+ it to the keyboard mapping. Thanks to Vlad Harchev for pointing
+ out problems with non-ascii capitalisation. */
+
+ if (freeIndex == -1) {
+ ErrorF("KbdAddEvent: ignoring KeySym 0x%x - no free KeyCodes\n",
+ (int)keySym);
+ return;
+ }
+
+ keyCode = MIN_KEY_CODE + freeIndex / keySyms->mapWidth;
+
+ vncXConvertCase(keySym, &lower, &upper);
+
+ if (lower == upper) {
+ keySyms->map[freeIndex] = keySym;
+
+ } else {
+ keySyms->map[freeIndex] = lower;
+ keySyms->map[freeIndex+1] = upper;
+
+ if (keySym == lower)
+ shiftMustBeReleased = TRUE;
+ else
+ shiftMustBePressed = TRUE;
+ }
+
+ SendMappingNotify(MappingKeyboard, keyCode, 1, serverClient);
+
+ ErrorF("KbdAddEvent: unknown KeySym 0x%x - allocating KeyCode %d\n",
+ (int)keySym, keyCode);
+ }
+
+ if (down) {
+ if (shiftMustBePressed && !(kbdDevice->key->state & ShiftMask)) {
+ fakeShiftPress = TRUE;
+ EnqueueKey(kbdDevice, KeyPress, SHIFT_L_KEY_CODE);
+ }
+ if (shiftMustBeReleased && (kbdDevice->key->state & ShiftMask)) {
+ if (KEY_IS_PRESSED(SHIFT_L_KEY_CODE)) {
+ fakeShiftLRelease = TRUE;
+ EnqueueKey(kbdDevice, KeyRelease, SHIFT_L_KEY_CODE);
+ }
+ if (KEY_IS_PRESSED(SHIFT_R_KEY_CODE)) {
+ fakeShiftRRelease = TRUE;
+ EnqueueKey(kbdDevice, KeyRelease, SHIFT_R_KEY_CODE);
+ }
+ }
+ }
+
+ EnqueueKey(kbdDevice, type, keyCode);
+
+ if (fakeShiftPress) {
+ EnqueueKey(kbdDevice, KeyRelease, SHIFT_L_KEY_CODE);
+ }
+ if (fakeShiftLRelease) {
+ EnqueueKey(kbdDevice, KeyPress, SHIFT_L_KEY_CODE);
+ }
+ if (fakeShiftRRelease) {
+ EnqueueKey(kbdDevice, KeyPress, SHIFT_R_KEY_CODE);
+ }
+}
+
+
+/*
+ * Called when the rfbserver receives a rfbPointerEvent event from a client.
+ * Put an X mouse event into the event queue.
+ */
+void
+PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+ int i;
+ static int oldButtonMask = 0;
+
+#ifdef CORBA
+ if (cl) {
+ CARD32 clientId = cl->sock;
+ ChangeWindowProperty(WindowTable[0], VNC_LAST_CLIENT_ID, XA_INTEGER,
+ 32, PropModeReplace, 1, (pointer)&clientId, TRUE);
+ }
+#endif
+
+#ifdef DMXVNC
+ dmxCoreMotion(&ptrDevice->public, x, y, 0, DMX_BLOCK);
+#else
+ EnqueueMotion(ptrDevice, x, y );
+#endif
+
+ for (i = 0; i < 5; i++) {
+ if ((buttonMask ^ oldButtonMask) & (1<<i)) {
+ int type, detail;
+ if (buttonMask & (1<<i)) {
+ type = ButtonPress;
+ detail = i + 1;
+ } else {
+ type = ButtonRelease;
+ detail = i + 1;
+ }
+ EnqueueButton(ptrDevice, type, detail);
+ }
+ }
+
+ oldButtonMask = buttonMask;
+}
+
+void
+KbdReleaseAllKeys(void)
+{
+ int i, j;
+
+ if (!kbdDevice)
+ return;
+
+ for (i = 0; i < DOWN_LENGTH; i++) {
+ if (kbdDevice->key->down[i] != 0) {
+ for (j = 0; j < 8; j++) {
+ if (kbdDevice->key->down[i] & (1 << j)) {
+ int detail = (i << 3) | j;
+ EnqueueKey(kbdDevice, KeyRelease, detail);
+ }
+ }
+ }
+ }
+}
+
+
+/* copied from Xlib source */
+
+static void vncXConvertCase(KeySym sym, KeySym *lower, KeySym *upper)
+{
+ *lower = sym;
+ *upper = sym;
+ switch(sym >> 8) {
+ case 0: /* Latin 1 */
+ if ((sym >= XK_A) && (sym <= XK_Z))
+ *lower += (XK_a - XK_A);
+ else if ((sym >= XK_a) && (sym <= XK_z))
+ *upper -= (XK_a - XK_A);
+ else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
+ *lower += (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
+ *upper -= (XK_agrave - XK_Agrave);
+ else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
+ *lower += (XK_oslash - XK_Ooblique);
+ else if ((sym >= XK_oslash) && (sym <= XK_thorn))
+ *upper -= (XK_oslash - XK_Ooblique);
+ break;
+ case 1: /* Latin 2 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym == XK_Aogonek)
+ *lower = XK_aogonek;
+ else if (sym >= XK_Lstroke && sym <= XK_Sacute)
+ *lower += (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_Scaron && sym <= XK_Zacute)
+ *lower += (XK_scaron - XK_Scaron);
+ else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
+ *lower += (XK_zcaron - XK_Zcaron);
+ else if (sym == XK_aogonek)
+ *upper = XK_Aogonek;
+ else if (sym >= XK_lstroke && sym <= XK_sacute)
+ *upper -= (XK_lstroke - XK_Lstroke);
+ else if (sym >= XK_scaron && sym <= XK_zacute)
+ *upper -= (XK_scaron - XK_Scaron);
+ else if (sym >= XK_zcaron && sym <= XK_zabovedot)
+ *upper -= (XK_zcaron - XK_Zcaron);
+ else if (sym >= XK_Racute && sym <= XK_Tcedilla)
+ *lower += (XK_racute - XK_Racute);
+ else if (sym >= XK_racute && sym <= XK_tcedilla)
+ *upper -= (XK_racute - XK_Racute);
+ break;
+ case 2: /* Latin 3 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
+ *lower += (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
+ *lower += (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
+ *upper -= (XK_hstroke - XK_Hstroke);
+ else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
+ *upper -= (XK_gbreve - XK_Gbreve);
+ else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
+ *lower += (XK_cabovedot - XK_Cabovedot);
+ else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
+ *upper -= (XK_cabovedot - XK_Cabovedot);
+ break;
+ case 3: /* Latin 4 */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Rcedilla && sym <= XK_Tslash)
+ *lower += (XK_rcedilla - XK_Rcedilla);
+ else if (sym >= XK_rcedilla && sym <= XK_tslash)
+ *upper -= (XK_rcedilla - XK_Rcedilla);
+ else if (sym == XK_ENG)
+ *lower = XK_eng;
+ else if (sym == XK_eng)
+ *upper = XK_ENG;
+ else if (sym >= XK_Amacron && sym <= XK_Umacron)
+ *lower += (XK_amacron - XK_Amacron);
+ else if (sym >= XK_amacron && sym <= XK_umacron)
+ *upper -= (XK_amacron - XK_Amacron);
+ break;
+ case 6: /* Cyrillic */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
+ *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
+ *upper += (XK_Serbian_DJE - XK_Serbian_dje);
+ else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
+ *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
+ *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
+ break;
+ case 7: /* Greek */
+ /* Assume the KeySym is a legal value (ignore discontinuities) */
+ if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
+ *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
+ sym != XK_Greek_iotaaccentdieresis &&
+ sym != XK_Greek_upsilonaccentdieresis)
+ *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
+ else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
+ *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
+ else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
+ sym != XK_Greek_finalsmallsigma)
+ *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
+ break;
+ }
+}
--- xorg-server-1.7.4/hw/vnc/keyboard.h
+++ xorg-server-1.7.4/hw/vnc/keyboard.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+#define MIN_KEY_CODE 8
+#define MAX_KEY_CODE 255
+#define NO_OF_KEYS (MAX_KEY_CODE - MIN_KEY_CODE + 1)
+#define GLYPHS_PER_KEY 4
+
+#define CONTROL_L_KEY_CODE (MIN_KEY_CODE + 29)
+#define CONTROL_R_KEY_CODE (MIN_KEY_CODE + 101)
+#define SHIFT_L_KEY_CODE (MIN_KEY_CODE + 42)
+#define SHIFT_R_KEY_CODE (MIN_KEY_CODE + 54)
+#define META_L_KEY_CODE (MIN_KEY_CODE + 107)
+#define META_R_KEY_CODE (MIN_KEY_CODE + 108)
+#define ALT_L_KEY_CODE (MIN_KEY_CODE + 56)
+#define ALT_R_KEY_CODE (MIN_KEY_CODE + 105)
+
+static KeySym map[MAX_KEY_CODE * GLYPHS_PER_KEY] = {
+ /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol,
+ /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol,
+ /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol,
+ /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol,
+ /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol,
+ /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol,
+ /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol,
+ /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol,
+ /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol,
+ /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol,
+ /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol,
+ /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol,
+ /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol,
+ /* 0x10 */ XK_q, XK_Q, NoSymbol, NoSymbol,
+ /* 0x11 */ XK_w, XK_W, NoSymbol, NoSymbol,
+ /* 0x12 */ XK_e, XK_E, NoSymbol, NoSymbol,
+ /* 0x13 */ XK_r, XK_R, NoSymbol, NoSymbol,
+ /* 0x14 */ XK_t, XK_T, NoSymbol, NoSymbol,
+ /* 0x15 */ XK_y, XK_Y, NoSymbol, NoSymbol,
+ /* 0x16 */ XK_u, XK_U, NoSymbol, NoSymbol,
+ /* 0x17 */ XK_i, XK_I, NoSymbol, NoSymbol,
+ /* 0x18 */ XK_o, XK_O, NoSymbol, NoSymbol,
+ /* 0x19 */ XK_p, XK_P, NoSymbol, NoSymbol,
+ /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol,
+ /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol,
+ /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x1e */ XK_a, XK_A, NoSymbol, NoSymbol,
+ /* 0x1f */ XK_s, XK_S, NoSymbol, NoSymbol,
+ /* 0x20 */ XK_d, XK_D, NoSymbol, NoSymbol,
+ /* 0x21 */ XK_f, XK_F, NoSymbol, NoSymbol,
+ /* 0x22 */ XK_g, XK_G, NoSymbol, NoSymbol,
+ /* 0x23 */ XK_h, XK_H, NoSymbol, NoSymbol,
+ /* 0x24 */ XK_j, XK_J, NoSymbol, NoSymbol,
+ /* 0x25 */ XK_k, XK_K, NoSymbol, NoSymbol,
+ /* 0x26 */ XK_l, XK_L, NoSymbol, NoSymbol,
+ /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol,
+ /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol,
+ /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol,
+ /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol,
+ /* 0x2c */ XK_z, XK_Z, NoSymbol, NoSymbol,
+ /* 0x2d */ XK_x, XK_X, NoSymbol, NoSymbol,
+ /* 0x2e */ XK_c, XK_C, NoSymbol, NoSymbol,
+ /* 0x2f */ XK_v, XK_V, NoSymbol, NoSymbol,
+ /* 0x30 */ XK_b, XK_B, NoSymbol, NoSymbol,
+ /* 0x31 */ XK_n, XK_N, NoSymbol, NoSymbol,
+ /* 0x32 */ XK_m, XK_M, NoSymbol, NoSymbol,
+ /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol,
+ /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol,
+ /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol,
+ /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol,
+ /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol,
+ /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol,
+ /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol,
+ /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol,
+ /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol,
+ /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol,
+ /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol,
+ /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol,
+ /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol,
+ /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol,
+ /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol,
+ /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol,
+ /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x59 */ XK_Home, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5a */ XK_Up, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5b */ XK_Prior, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5c */ XK_Left, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5e */ XK_Right, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x5f */ XK_End, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x60 */ XK_Down, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x61 */ XK_Next, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x62 */ XK_Insert, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x63 */ XK_Delete, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x64 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x65 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x66 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x67 */ XK_Print, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x68 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x69 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol,
+ /* 0x6a */ XK_Break, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6b */ XK_Meta_L, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6c */ XK_Meta_R, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6d */ XK_Menu, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6e */ XK_F13, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x6f */ XK_F14, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x70 */ XK_F15, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x71 */ XK_F16, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x72 */ XK_F17, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x73 */ XK_backslash, XK_underscore, NoSymbol, NoSymbol,
+ /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x77 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x79 */ XK_Henkan, XK_Mode_switch, NoSymbol, NoSymbol,
+ /* 0x7a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7b */ XK_Muhenkan, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7d */ XK_backslash, XK_bar, NoSymbol, NoSymbol,
+ /* 0x7e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+ /* 0x7f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
+};
+
+#define N_PREDEFINED_KEYS (sizeof(map) / (sizeof(KeySym) * GLYPHS_PER_KEY))
--- xorg-server-1.7.4/hw/vnc/loginauth.c
+++ xorg-server-1.7.4/hw/vnc/loginauth.c
@@ -0,0 +1,143 @@
+/*
+ * loginauth.c - deal with login-style Unix authentication.
+ *
+ * This file implements the UnixLogin authentication protocol when setting up
+ * an RFB connection.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2003 Constantin Kaplinsky. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#ifdef linux
+#include "/usr/include/shadow.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#define _XOPEN_SOURCE
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include "rfb.h"
+
+void rfbLoginAuthProcessClientMessage(rfbClientPtr cl)
+{
+ int n1 = 0, n2 = 0;
+ CARD32 loginLen, passwdLen, authResult;
+ char *loginBuf, *passwdBuf;
+ struct passwd *ps;
+ char *encPasswd1, *encPasswd2;
+ Bool ok;
+
+ if ((n1 = ReadExact(cl->sock, (char *)&loginLen,
+ sizeof(loginLen))) <= 0 ||
+ (n2 = ReadExact(cl->sock, (char *)&passwdLen,
+ sizeof(passwdLen))) <= 0) {
+ if (n1 != 0 || n2 != 0)
+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ loginLen = Swap32IfLE(loginLen);
+ passwdLen = Swap32IfLE(passwdLen);
+ loginBuf = (char *)xalloc(loginLen + 1);
+ passwdBuf = (char *)xalloc(passwdLen + 1);
+
+ n1 = n2 = 0;
+ if ((n1 = ReadExact(cl->sock, loginBuf, loginLen)) <= 0 ||
+ (n2 = ReadExact(cl->sock, passwdBuf, passwdLen)) <= 0) {
+ if (n1 != 0 || n2 != 0)
+ rfbLogPerror("rfbLoginAuthProcessClientMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ loginBuf[loginLen] = '\0';
+ passwdBuf[passwdLen] = '\0';
+
+ encPasswd1 = encPasswd2 = NULL;
+
+ ps = getpwnam(loginBuf);
+ if (ps == NULL) {
+ rfbLog("rfbLoginAuthProcessClientMessage: "
+ "Cannot get password file entry for \"%s\"\n", loginBuf);
+ } else {
+ encPasswd1 = ps->pw_passwd;
+#ifdef linux
+ if (strlen(ps->pw_passwd) == 1) {
+ struct spwd *sps;
+
+ sps = getspnam(loginBuf);
+ if (sps == NULL) {
+ rfbLog("rfbLoginAuthProcessClientMessage:"
+ " getspnam() failed for user \"%s\"\n", loginBuf);
+ } else {
+ encPasswd1 = sps->sp_pwdp;
+ }
+ }
+#endif
+ encPasswd2 = (char *)crypt(passwdBuf, encPasswd1);
+ memset(passwdBuf, 0, strlen(passwdBuf));
+ }
+
+ ok = FALSE;
+ if (encPasswd1 != NULL && encPasswd2 != NULL) {
+ if (strcmp(encPasswd1, encPasswd2) == 0)
+ ok = TRUE;
+ }
+
+ if (!ok) {
+ rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
+ cl->host);
+
+ if (rfbAuthConsiderBlocking(cl)) {
+ authResult = Swap32IfLE(rfbVncAuthTooMany);
+ } else {
+ authResult = Swap32IfLE(rfbVncAuthFailed);
+ }
+
+ if (WriteExact(cl->sock, (char *)&authResult,
+ sizeof(authResult)) < 0) {
+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write");
+ }
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ rfbAuthUnblock(cl);
+
+ cl->login = strdup(loginBuf);
+ rfbLog("Login-style authentication passed for user %s at %s\n",
+ cl->login, cl->host);
+
+ authResult = Swap32IfLE(rfbVncAuthOK);
+
+ if (WriteExact(cl->sock, (char *)&authResult, sizeof(authResult)) < 0) {
+ rfbLogPerror("rfbLoginAuthProcessClientMessage: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ cl->state = RFB_INITIALISATION;
+}
+
--- xorg-server-1.7.4/hw/vnc/rdp.c
+++ xorg-server-1.7.4/hw/vnc/rdp.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2004 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include "rfb.h"
+
+typedef struct rdpClientRec {
+ ScreenPtr pScreen;
+} rdpClientRec, *rdpClientPtr;
+
+typedef struct rdpInRec {
+ char version;
+ char pad;
+ short length;
+ char hdrlen;
+ unsigned char pdu;
+} rdpInRec, *rdpInPtr;
+
+static void
+rdpCloseSock(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ close(pVNC->rdpListenSock);
+ RemoveEnabledDevice(pVNC->rdpListenSock);
+ pVNC->rdpListenSock = -1;
+}
+
+/*
+ * rdpNewClient is called when a new connection has been made by whatever
+ * means.
+ */
+
+static rdpClientPtr
+rdpNewClient(ScreenPtr pScreen, int sock)
+{
+ rdpInRec in;
+ rdpClientPtr cl;
+ BoxRec box;
+ struct sockaddr_in addr;
+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in);
+ VNCSCREENPTR(pScreen);
+ int i;
+
+ cl = (rdpClientPtr)xalloc(sizeof(rdpClientRec));
+
+ cl->pScreen = pScreen;
+
+ in.version = 3;
+ in.pad = 0;
+ in.length = 0x600; /* big endian */
+ in.hdrlen = 0x00;
+ in.pdu = 0xCC;
+
+ if (WriteExact(sock, (char *)&in, sizeof(rdpInRec)) < 0) {
+ rfbLogPerror("rfbNewClient: write");
+ rdpCloseSock(pScreen);
+ return NULL;
+ }
+
+ return cl;
+}
+/*
+ * rdpCheckFds is called from ProcessInputEvents to check for input on the
+ * HTTP socket(s). If there is input to process, rdpProcessInput is called.
+ */
+
+void
+rdpCheckFds(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ int nfds;
+ fd_set fds;
+ struct timeval tv;
+ struct sockaddr_in addr;
+ int sock;
+ const int one =1;
+ SOCKLEN_T addrlen = sizeof(addr);
+
+ FD_ZERO(&fds);
+ FD_SET(pVNC->rdpListenSock, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ nfds = select(pVNC->rdpListenSock + 1, &fds, NULL, NULL, &tv);
+ if (nfds == 0) {
+ return;
+ }
+ if (nfds < 0) {
+ if (errno != EINTR)
+ rfbLogPerror("httpCheckFds: select");
+ return;
+ }
+
+ if (pVNC->rdpListenSock != -1 && FD_ISSET(pVNC->rdpListenSock, &fds)) {
+
+ if ((sock = accept(pVNC->rdpListenSock,
+ (struct sockaddr *)&addr, &addrlen)) < 0) {
+ rfbLogPerror("rdpCheckFds: accept");
+ return;
+ }
+
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("rdpCheckFds: fcntl");
+ close(sock);
+ return;
+ }
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("rdpCheckFds: setsockopt");
+ close(sock);
+ return;
+ }
+
+ rfbLog("\n");
+
+ rfbLog("Got RDP connection from client %s\n", inet_ntoa(addr.sin_addr));
+
+ AddEnabledDevice(sock);
+
+ rdpNewClient(pScreen, sock);
+ }
+}
--- xorg-server-1.7.4/hw/vnc/rfb.h
+++ xorg-server-1.7.4/hw/vnc/rfb.h
@@ -0,0 +1,751 @@
+/*
+ * rfb.h - header file for RFB DDX implementation.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2000-2004 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef RFB_H_INCLUDED
+#define RFB_H_INCLUDED
+
+#ifdef HAVE_DMX_CONFIG_H
+#include "dmx-config.h"
+#endif
+
+#ifdef DMXVNC
+#include <dmx.h>
+#else
+#include <dix-config.h>
+#endif
+
+#include <zlib.h>
+#ifdef XFREE86VNC
+#include "xf86.h"
+#endif
+#include "scrnintstr.h"
+#include "colormapst.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "regionstr.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "mipointer.h"
+#include <rfbproto.h>
+#include <vncauth.h>
+#define _VNC_SERVER
+#include <X11/extensions/vnc.h>
+#include "picturestr.h"
+
+#if defined(sun) || defined(hpux)
+#define SOCKLEN_T int
+#else
+#define SOCKLEN_T socklen_t
+#endif
+
+/* It's a good idea to keep these values a bit greater than required. */
+#define MAX_ENCODINGS 10
+#define MAX_SECURITY_TYPES 4
+#define MAX_TUNNELING_CAPS 16
+#define MAX_AUTH_CAPS 16
+
+/*
+ * HTTP_BUF_SIZE for http transfers
+ */
+#define HTTP_BUF_SIZE 32768
+
+/*
+ * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the
+ * framebuffer. So for a max screen width of say 2K with 32-bit pixels this
+ * means 8K minimum.
+ */
+#define UPDATE_BUF_SIZE 30000
+
+extern DevPrivateKey VNCScreenKey;
+extern DevPrivateKey rfbGCKey;
+
+#if XFREE86VNC || defined(DMXVNC)
+#include "vncint.h"
+#define VNCSCREENPTR(ptr) \
+ vncScreenPtr pVNC = VNCPTR(ptr)
+#else
+#define VNCSCREENPTR(ptr) \
+/* Soon \
+ rfbScreenInfoPtr pVNC = rfbScreen[ptr->myNum] \
+*/ \
+ rfbScreenInfoPtr pVNC = &rfbScreen
+#endif
+
+/*
+ * Per-screen (framebuffer) structure. There is only one of these, since we
+ * don't allow the X server to have multiple screens.
+ */
+
+typedef struct
+{
+ int rfbPort;
+ int rdpPort;
+ int udpPort;
+ int rfbListenSock;
+ int rdpListenSock;
+ int udpSock;
+ int httpPort;
+ int httpListenSock;
+ int httpSock;
+ char * httpDir;
+ char buf[HTTP_BUF_SIZE];
+ Bool udpSockConnected;
+ char * rfbAuthPasswdFile;
+ size_t buf_filled;
+ int maxFd;
+ fd_set allFds;
+ Bool noCursor;
+ Bool rfbAlwaysShared;
+ Bool rfbNeverShared;
+ Bool rfbDontDisconnect;
+ Bool rfbUserAccept;
+ Bool rfbViewOnly;
+ ColormapPtr savedColormap;
+ ColormapPtr rfbInstalledColormap;
+ rfbPixelFormat rfbServerFormat;
+ Bool rfbAuthTooManyTries;
+ int rfbAuthTries;
+ Bool loginAuthEnabled;
+ struct in_addr interface;
+ OsTimerPtr timer;
+ unsigned char updateBuf[UPDATE_BUF_SIZE];
+ int ublen;
+ int width;
+ int paddedWidthInBytes;
+ int height;
+ int depth;
+ int bitsPerPixel;
+ int sizeInBytes;
+ unsigned char *pfbMemory;
+ Pixel blackPixel;
+ Pixel whitePixel;
+
+ /* The following two members are used to minimise the amount of unnecessary
+ drawing caused by cursor movement. Whenever any drawing affects the
+ part of the screen where the cursor is, the cursor is removed first and
+ then the drawing is done (this is what the sprite routines test for).
+ Afterwards, however, we do not replace the cursor, even when the cursor
+ is logically being moved across the screen. We only draw the cursor
+ again just as we are about to send the client a framebuffer update.
+
+ We need to be careful when removing and drawing the cursor because of
+ their relationship with the normal drawing routines. The drawing
+ routines can invoke the cursor routines, but also the cursor routines
+ themselves end up invoking drawing routines.
+
+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by
+ doing a CopyArea from a pixmap to the screen, where the pixmap contains
+ the saved contents of the screen under the cursor. Before doing this,
+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
+ (recursively!) remove the cursor before doing it.
+
+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to
+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so
+ that PushPixels doesn't think it has to remove the cursor first.
+ Obviously cursorIsDrawn is set to TRUE afterwards.
+
+ Another problem we face is that drawing routines sometimes cause a
+ framebuffer update to be sent to the RFB client. When the RFB client is
+ already waiting for a framebuffer update and some drawing to the
+ framebuffer then happens, the drawing routine sees that the client is
+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is
+ called. However, if the original drawing routine was actually called
+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
+ want this to happen. So both the cursor routines set
+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check
+ this before calling rfbSendFramebufferUpdate. */
+
+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
+ cursor */
+
+ /* wrapped screen functions */
+
+ CloseScreenProcPtr CloseScreen;
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ RestoreAreasProcPtr RestoreAreas;
+ ScreenWakeupHandlerProcPtr WakeupHandler;
+#ifdef CHROMIUM
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ PositionWindowProcPtr PositionWindow;
+ ClipNotifyProcPtr ClipNotify;
+#endif
+#ifdef RENDER
+ CompositeProcPtr Composite;
+#endif
+
+} rfbScreenInfo, *rfbScreenInfoPtr;
+
+
+/*
+ * rfbTranslateFnType is the type of translation functions.
+ */
+
+struct rfbClientRec;
+typedef void (*rfbTranslateFnType)(ScreenPtr pScreen,
+ char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ unsigned char *optr,
+ int bytesBetweenInputLines,
+ int width, int height,
+ int x, int y);
+
+
+/*
+ * Per-client structure.
+ */
+
+typedef struct rfbClientRec {
+ int sock;
+ char *host;
+ char *login;
+
+ int protocol_minor_ver; /* RFB protocol minor version in use. */
+ Bool protocol_tightvnc; /* TightVNC protocol extensions enabled */
+
+ /* Possible client states: */
+
+ enum {
+ RFB_PROTOCOL_VERSION, /* establishing protocol version */
+ RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */
+ RFB_TUNNELING_TYPE, /* establishing tunneling (RFB v.3.7t) */
+ RFB_AUTH_TYPE, /* negotiating authentication (RFB v.3.7t) */
+ RFB_AUTHENTICATION, /* authenticating (VNC authentication) */
+ RFB_INITIALISATION, /* sending initialisation messages */
+ RFB_NORMAL /* normal protocol messages */
+ } state;
+
+ Bool viewOnly; /* Do not accept input from this client. */
+
+ Bool reverseConnection;
+
+ Bool readyForSetColourMapEntries;
+
+ Bool useCopyRect;
+ int preferredEncoding;
+ int correMaxWidth, correMaxHeight;
+
+ /* The list of security types sent to this client (protocol 3.7).
+ Note that the first entry is the number of list items following. */
+
+ CARD8 securityTypes[MAX_SECURITY_TYPES + 1];
+
+ /* Lists of capability codes sent to clients. We remember these
+ lists to restrict clients from choosing those tunneling and
+ authentication types that were not advertised. */
+
+ int nAuthCaps;
+ CARD32 authCaps[MAX_AUTH_CAPS];
+
+ /* This is not useful while we don't support tunneling:
+ int nTunnelingCaps;
+ CARD32 tunnelingCaps[MAX_TUNNELING_CAPS]; */
+
+ /* The following member is only used during VNC authentication */
+
+ CARD8 authChallenge[CHALLENGESIZE];
+
+ /* The following members represent the update needed to get the client's
+ framebuffer from its present state to the current state of our
+ framebuffer.
+
+ If the client does not accept CopyRect encoding then the update is
+ simply represented as the region of the screen which has been modified
+ (modifiedRegion).
+
+ If the client does accept CopyRect encoding, then the update consists of
+ two parts. First we have a single copy from one region of the screen to
+ another (the destination of the copy is copyRegion), and second we have
+ the region of the screen which has been modified in some other way
+ (modifiedRegion).
+
+ Although the copy is of a single region, this region may have many
+ rectangles. When sending an update, the copyRegion is always sent
+ before the modifiedRegion. This is because the modifiedRegion may
+ overlap parts of the screen which are in the source of the copy.
+
+ In fact during normal processing, the modifiedRegion may even overlap
+ the destination copyRegion. Just before an update is sent we remove
+ from the copyRegion anything in the modifiedRegion. */
+
+ RegionRec copyRegion; /* the destination region of the copy */
+ int copyDX, copyDY; /* the translation by which the copy happens */
+
+ RegionRec modifiedRegion; /* the region of the screen modified in any
+ other way */
+
+ /* As part of the FramebufferUpdateRequest, a client can express interest
+ in a subrectangle of the whole framebuffer. This is stored in the
+ requestedRegion member. In the normal case this is the whole
+ framebuffer if the client is ready, empty if it's not. */
+
+ RegionRec requestedRegion;
+
+ /* The following members represent the state of the "deferred update" timer
+ - when the framebuffer is modified and the client is ready, in most
+ cases it is more efficient to defer sending the update by a few
+ milliseconds so that several changes to the framebuffer can be combined
+ into a single update. */
+
+ Bool deferredUpdateScheduled;
+ OsTimerPtr deferredUpdateTimer;
+
+ /* translateFn points to the translation function which is used to copy
+ and translate a rectangle from the framebuffer to an output buffer. */
+
+ rfbTranslateFnType translateFn;
+
+ char *translateLookupTable;
+
+ rfbPixelFormat format;
+
+ /* statistics */
+
+ int rfbBytesSent[MAX_ENCODINGS];
+ int rfbRectanglesSent[MAX_ENCODINGS];
+ int rfbLastRectMarkersSent;
+ int rfbLastRectBytesSent;
+ int rfbCursorShapeBytesSent;
+ int rfbCursorShapeUpdatesSent;
+ int rfbCursorPosBytesSent;
+ int rfbCursorPosUpdatesSent;
+ int rfbFramebufferUpdateMessagesSent;
+ int rfbRawBytesEquivalent;
+ int rfbKeyEventsRcvd;
+ int rfbPointerEventsRcvd;
+
+ /* zlib encoding -- necessary compression state info per client */
+
+ struct z_stream_s compStream;
+ Bool compStreamInited;
+
+ CARD32 zlibCompressLevel;
+
+ /* tight encoding -- preserve zlib streams' state for each client */
+
+ z_stream zsStruct[4];
+ Bool zsActive[4];
+ int zsLevel[4];
+ int tightCompressLevel;
+ int tightQualityLevel;
+
+ Bool enableLastRectEncoding; /* client supports LastRect encoding */
+ Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
+ Bool enableCursorPosUpdates; /* client supports PointerPos updates */
+#ifdef CHROMIUM
+ Bool enableChromiumEncoding; /* client supports Chromium encoding */
+#endif
+ Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
+ Bool cursorWasChanged; /* cursor shape update should be sent */
+ Bool cursorWasMoved; /* cursor position update should be sent */
+
+ int cursorX, cursorY; /* client's cursor position */
+
+ struct rfbClientRec *next;
+
+ ScreenPtr pScreen;
+ int userAccepted;
+
+#ifdef CHROMIUM
+ unsigned int chromium_port;
+ unsigned int chromium_msport;
+#endif
+} rfbClientRec, *rfbClientPtr;
+
+#ifdef CHROMIUM
+typedef struct CRWindowTable {
+ unsigned long CRwinId;
+ unsigned long XwinId;
+ BoxPtr clipRects;
+ int numRects;
+ struct CRWindowTable *next;
+} CRWindowTable, *CRWindowTablePtr;
+
+extern struct CRWindowTable *windowTable;
+#endif
+
+/*
+ * This macro is used to test whether there is a framebuffer update needing to
+ * be sent to the client.
+ */
+
+#define FB_UPDATE_PENDING(cl) \
+ ((!(cl)->enableCursorShapeUpdates && !pVNC->cursorIsDrawn) || \
+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
+ ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \
+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->copyRegion) || \
+ REGION_NOTEMPTY(((cl)->pScreen),&(cl)->modifiedRegion))
+
+/*
+ * This macro creates an empty region (ie. a region with no areas) if it is
+ * given a rectangle with a width or height of zero. It appears that
+ * REGION_INTERSECT does not quite do the right thing with zero-width
+ * rectangles, but it should with completely empty regions.
+ */
+
+#define SAFE_REGION_INIT(pscreen, preg, rect, size) \
+{ \
+ if ( ( (rect) ) && \
+ ( ( (rect)->x2 == (rect)->x1 ) || \
+ ( (rect)->y2 == (rect)->y1 ) ) ) { \
+ REGION_NULL( (pscreen), (preg) ); \
+ } else { \
+ REGION_INIT( (pscreen), (preg), (rect), (size) ); \
+ } \
+}
+
+/*
+ * An rfbGCRec is where we store the pointers to the original GC funcs and ops
+ * which we wrap (NULL means not wrapped).
+ */
+
+typedef struct {
+ GCFuncs *wrapFuncs;
+ GCOps *wrapOps;
+} rfbGCRec, *rfbGCPtr;
+
+
+
+/*
+ * Macros for endian swapping.
+ */
+
+#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
+
+#define Swap32(l) (((l) >> 24) | \
+ (((l) & 0x00ff0000) >> 8) | \
+ (((l) & 0x0000ff00) << 8) | \
+ ((l) << 24))
+
+static const int rfbEndianTest = 1;
+
+#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s))
+
+#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l))
+
+
+/*
+ * Macro to fill in an rfbCapabilityInfo structure (protocol 3.130).
+ * Normally, using macros is no good, but this macro saves us from
+ * writing constants twice -- it constructs signature names from codes.
+ * Note that "code_sym" argument should be a single symbol, not an expression.
+ */
+
+#define SetCapInfo(cap_ptr, code_sym, vendor) \
+{ \
+ rfbCapabilityInfo *pcap; \
+ pcap = (cap_ptr); \
+ pcap->code = Swap32IfLE(code_sym); \
+ memcpy(pcap->vendorSignature, (vendor), \
+ sz_rfbCapabilityInfoVendor); \
+ memcpy(pcap->nameSignature, sig_##code_sym, \
+ sz_rfbCapabilityInfoName); \
+}
+
+
+/* init.c */
+
+extern char *desktopName;
+extern char rfbThisHost[];
+extern Atom VNC_LAST_CLIENT_ID;
+
+extern rfbScreenInfo rfbScreen;
+
+extern int inetdSock;
+
+extern int rfbBitsPerPixel(int depth);
+extern void rfbLog(char *format, ...);
+extern void rfbLogPerror(char *str);
+
+
+/* sockets.c */
+
+extern int rfbMaxClientWait;
+
+extern Bool rfbInitSockets(ScreenPtr pScreen);
+extern void rfbDisconnectUDPSock(ScreenPtr pScreen);
+extern void rfbCloseSock(ScreenPtr pScreen, int sock);
+extern void rfbCheckFds(ScreenPtr pScreen);
+extern void rfbWaitForClient(int sock);
+extern int rfbConnect(ScreenPtr pScreen, char *host, int port);
+
+extern int ReadExact(int sock, char *buf, int len);
+extern int WriteExact(int sock, char *buf, int len);
+extern int ListenOnTCPPort(ScreenPtr pScreen, int port);
+extern int ListenOnUDPPort(ScreenPtr pScreen, int port);
+extern int ConnectToTcpAddr(char *host, int port);
+
+
+/* cmap.c */
+
+
+extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps);
+extern void rfbInstallColormap(ColormapPtr pmap);
+extern void rfbUninstallColormap(ColormapPtr pmap);
+extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs);
+
+
+/* draw.c */
+
+extern int rfbDeferUpdateTime;
+
+extern void
+rfbComposite(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height
+);
+
+extern void rfbGlyphs(
+ CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlistInit,
+ GlyphListPtr listInit,
+ GlyphPtr *glyphsInit
+);
+extern Bool rfbCloseScreen(int,ScreenPtr);
+extern Bool rfbCreateGC(GCPtr);
+extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what);
+extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what);
+extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr);
+#ifdef CHROMIUM
+extern Bool rfbRealizeWindow(WindowPtr);
+extern Bool rfbUnrealizeWindow(WindowPtr);
+extern Bool rfbDestroyWindow(WindowPtr);
+extern void rfbResizeWindow(WindowPtr, int x, int y, unsigned int w, unsigned int h, WindowPtr pSib);
+extern Bool rfbPositionWindow(WindowPtr, int x, int y);
+extern void rfbClipNotify(WindowPtr, int x, int y);
+#endif
+extern void rfbClearToBackground(WindowPtr, int x, int y, int w,
+ int h, Bool generateExposures);
+extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr);
+extern void rfbScheduleUpdate(ScreenPtr pScreen);
+
+/* dispcur.c */
+extern Bool rfbDCInitialize(ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs);
+
+
+/* cutpaste.c */
+
+extern void rfbSetXCutText(char *str, int len);
+extern void rfbGotXCutText(char *str, int len);
+
+
+/* kbdptr.c */
+
+extern Bool compatibleKbd;
+extern unsigned char ptrAcceleration;
+
+extern void PtrDeviceInit(void);
+extern void PtrDeviceOn(DeviceIntPtr pDev);
+extern void PtrDeviceOff(void);
+extern void PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl);
+extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl);
+
+extern void KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap);
+extern void KbdDeviceOn(void);
+extern void KbdDeviceOff(void);
+extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl);
+extern void KbdReleaseAllKeys(void);
+
+extern void vncSetKeyboardDevice(DeviceIntPtr kbd);
+extern void vncSetPointerDevice(DeviceIntPtr ptr);
+
+
+/* rfbserver.c */
+
+
+extern rfbClientPtr rfbClientHead;
+extern rfbClientPtr pointerClient;
+
+extern void rfbNewClientConnection(ScreenPtr pScreen, int sock);
+extern rfbClientPtr rfbReverseConnection(ScreenPtr pScreen, char *host, int port);
+extern void rfbRootPropertyChange(ScreenPtr pScreen);
+extern void rfbClientConnectionGone(int sock);
+extern void rfbProcessClientMessage(ScreenPtr pScreen, int sock);
+extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
+extern void rfbNewUDPConnection(int sock);
+extern void rfbProcessUDPInput(ScreenPtr pScreen, int sock);
+extern Bool rfbSendFramebufferUpdate(ScreenPtr pScreen, rfbClientPtr cl);
+extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h);
+extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
+extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour,
+ int nColours);
+extern void rfbSendBell(void);
+extern void rfbSendServerCutText(char *str, int len);
+extern void rfbUserAllow(int sock, int accept);
+extern void rfbSetClip (WindowPtr pWin, BOOL enable);
+
+extern int GenerateVncConnectedEvent(int sock);
+extern int GenerateVncDisconnectedEvent(int sock);
+
+#ifdef CHROMIUM
+extern void rfbSendChromiumWindowShow(unsigned int winid, unsigned int show);
+extern void rfbSendChromiumWindowDestroy(unsigned int winid);
+extern void rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h);
+extern void rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects);
+#endif
+
+/* translate.c */
+
+extern Bool rfbEconomicTranslate;
+
+extern void rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ unsigned char *optr,
+ int bytesBetweenInputLines,
+ int width, int height,
+ int x, int y);
+extern Bool rfbSetTranslateFunction(rfbClientPtr cl);
+extern void rfbSetClientColourMaps(int firstColour, int nColours);
+extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour,
+ int nColours);
+
+
+/* httpd.c */
+
+extern Bool httpInitSockets(ScreenPtr pScreen);
+extern void httpCheckFds(ScreenPtr pScreen);
+
+
+/* vncInit.c */
+extern void VNCInitForDMX(void);
+extern void rfbWakeupHandlerDMX(void);
+
+
+/* vncext.c */
+
+#ifdef CHROMIUM
+extern void rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort, unsigned int mothershipPort);
+extern void rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long windowid);
+int GenerateVncChromiumConnectedEvent(int sock);
+#endif
+
+
+/* auth.c */
+
+extern void rfbAuthNewClient(rfbClientPtr cl);
+extern void rfbProcessClientSecurityType(rfbClientPtr cl);
+extern void rfbProcessClientTunnelingType(rfbClientPtr cl);
+extern void rfbProcessClientAuthType(rfbClientPtr cl);
+extern void rfbVncAuthProcessResponse(rfbClientPtr cl);
+
+/* Functions to prevent too many successive authentication failures */
+extern Bool rfbAuthConsiderBlocking(rfbClientPtr cl);
+extern void rfbAuthUnblock(rfbClientPtr cl);
+extern Bool rfbAuthIsBlocked(rfbClientPtr cl);
+
+/* loginauth.c */
+
+extern void rfbLoginAuthProcessClientMessage(rfbClientPtr cl);
+
+/* rre.c */
+
+extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* corre.c */
+
+extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* hextile.c */
+
+extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
+ int h);
+
+
+/* zlib.c */
+
+/* Minimum zlib rectangle size in bytes. Anything smaller will
+ * not compress well due to overhead.
+ */
+#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17)
+
+/* Set maximum zlib rectangle size in pixels. Always allow at least
+ * two scan lines.
+ */
+#define ZLIB_MAX_RECT_SIZE (128*256)
+#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \
+ ( min * 2 ) : ZLIB_MAX_RECT_SIZE )
+
+extern Bool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w,
+ int h);
+
+
+/* tight.c */
+
+#define TIGHT_DEFAULT_COMPRESSION 6
+
+extern Bool rfbTightDisableGradient;
+
+extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h);
+extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h);
+
+
+/* cursor.c */
+
+extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen);
+extern Bool rfbSendCursorPos(rfbClientPtr cl, ScreenPtr pScreen);
+
+
+/* stats.c */
+
+extern void rfbResetStats(rfbClientPtr cl);
+extern void rfbPrintStats(rfbClientPtr cl);
+
+
+/* dpms.c */
+
+extern Bool DPMSSupported(void);
+extern int DPSMGet(int *level);
+extern int DPMSSet(ClientPtr client, int level);
+
+
+#endif /* RFB_H_INCLUDED */
--- xorg-server-1.7.4/hw/vnc/rfbkeyb.c
+++ xorg-server-1.7.4/hw/vnc/rfbkeyb.c
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#if XFREE86VNC
+#ifndef XFree86LOADER
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include <misc.h>
+#include <xf86.h>
+#if !defined(DGUX)
+#include <xisb.h>
+#endif
+#include <xf86Xinput.h>
+#include <exevents.h> /* Needed for InitValuator/Proximity stuff */
+#include <mipointer.h>
+
+#ifdef XFree86LOADER
+#include <xf86Module.h>
+#endif
+#else
+#include <dix.h>
+#include <mipointer.h>
+#endif
+#include "rfb.h"
+
+
+extern void rfbSendBell(void);
+extern DeviceIntPtr kbdDevice;
+
+static const char *DEFAULTS[] = {
+ NULL
+};
+
+#include <X11/keysym.h>
+#include "keyboard.h"
+
+#ifdef XKB
+#include <X11/extensions/XKB.h>
+#include <X11/extensions/XKBstr.h>
+#include <X11/extensions/XKBsrv.h>
+
+#if XFREE86VNC
+ /*
+ * would like to use an XkbComponentNamesRec here but can't without
+ * pulling in a bunch of header files. :-(
+ */
+static char * xkbkeymap;
+static char * xkbkeycodes;
+static char * xkbtypes;
+static char * xkbcompat;
+static char * xkbsymbols;
+static char * xkbgeometry;
+static Bool xkbcomponents_specified;
+static char * xkbrules;
+static char * xkbmodel;
+static char * xkblayout;
+static char * xkbvariant;
+static char * xkboptions;
+#endif
+#endif
+
+void
+KbdDeviceInit(DeviceIntPtr pDevice, KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ int i;
+
+ for (i = 0; i < MAP_LENGTH; i++)
+ pModMap[i] = NoSymbol;
+
+ pModMap[CONTROL_L_KEY_CODE] = ControlMask;
+ pModMap[CONTROL_R_KEY_CODE] = ControlMask;
+ pModMap[SHIFT_L_KEY_CODE] = ShiftMask;
+ pModMap[SHIFT_R_KEY_CODE] = ShiftMask;
+ pModMap[META_L_KEY_CODE] = Mod1Mask;
+ pModMap[META_R_KEY_CODE] = Mod1Mask;
+ pModMap[ALT_L_KEY_CODE] = Mod1Mask;
+ pModMap[ALT_R_KEY_CODE] = Mod1Mask;
+
+ pKeySyms->minKeyCode = MIN_KEY_CODE;
+ pKeySyms->maxKeyCode = MAX_KEY_CODE;
+ pKeySyms->mapWidth = GLYPHS_PER_KEY;
+
+ pKeySyms->map = (KeySym *)xalloc(sizeof(KeySym)
+ * MAP_LENGTH * GLYPHS_PER_KEY);
+
+ if (!pKeySyms->map) {
+ ErrorF("xalloc failed\n");
+ exit(1);
+ }
+
+ for (i = 0; i < MAP_LENGTH * GLYPHS_PER_KEY; i++)
+ pKeySyms->map[i] = NoSymbol;
+
+ for (i = 0; i < N_PREDEFINED_KEYS * GLYPHS_PER_KEY; i++) {
+ pKeySyms->map[i] = map[i];
+ }
+}
+
+void
+KbdDeviceOn(void)
+{
+}
+
+
+void
+KbdDeviceOff(void)
+{
+}
+
+#if XFREE86VNC
+static int
+xf86rfbKeybControlProc(DeviceIntPtr device, int onoff)
+{
+ KeySymsRec keySyms;
+ CARD8 modMap[MAP_LENGTH];
+ DevicePtr pDev = (DevicePtr)device;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ vncSetKeyboardDevice(device);
+ KbdDeviceInit(device, &keySyms, modMap);
+#ifdef XKB
+ if (noXkbExtension) {
+#endif
+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+ (BellProcPtr)rfbSendBell,
+ (KbdCtrlProcPtr)NoopDDA);
+#ifdef XKB
+ } else {
+ XkbComponentNamesRec names;
+ if (xkbkeymap) {
+ names.keymap = xkbkeymap;
+ names.keycodes = NULL;
+ names.types = NULL;
+ names.compat = NULL;
+ names.symbols = NULL;
+ names.geometry = NULL;
+ } else {
+ names.keymap = NULL;
+ names.keycodes = xkbkeycodes;
+ names.types = xkbtypes;
+ names.compat = xkbcompat;
+ names.symbols = xkbsymbols;
+ names.geometry = xkbgeometry;
+ }
+ if ((xkbkeymap || xkbcomponents_specified)
+ && (xkbmodel == NULL || xkblayout == NULL)) {
+ xkbrules = NULL;
+ }
+#if 0
+ XkbSetRulesDflts(xkbrules, xkbmodel,
+ xkblayout, xkbvariant,
+ xkboptions);
+#endif
+ XkbInitKeyboardDeviceStruct(device,
+ &names,
+ &keySyms,
+ modMap,
+ (BellProcPtr)rfbSendBell,
+ (KbdCtrlProcPtr)NoopDDA);
+ }
+#endif
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ KbdDeviceOn();
+ break;
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ KbdDeviceOff();
+ break;
+ case DEVICE_CLOSE:
+ vncSetKeyboardDevice(NULL);
+ if (pDev->on)
+ KbdDeviceOff();
+ break;
+ }
+ return Success;
+}
+
+static void
+xf86rfbKeybUninit(InputDriverPtr drv,
+ InputInfoPtr pInfo,
+ int flags)
+{
+ xf86rfbKeybControlProc(pInfo->dev, DEVICE_OFF);
+}
+
+static InputInfoPtr
+xf86rfbKeybInit(InputDriverPtr drv,
+ IDevPtr dev,
+ int flags)
+{
+ InputInfoPtr pInfo;
+ char *s;
+ Bool from;
+
+ if (!(pInfo = xf86AllocateInput(drv, 0)))
+ return NULL;
+
+ /* Initialise the InputInfoRec. */
+ pInfo->name = dev->identifier;
+ pInfo->type_name = "rfbKeyb";
+ pInfo->flags = XI86_KEYBOARD_CAPABLE;
+ pInfo->device_control = xf86rfbKeybControlProc;
+ pInfo->read_input = NULL;
+#if 0
+ pInfo->motion_history_proc = NULL;
+#endif
+ pInfo->history_size = 0;
+ pInfo->control_proc = NULL;
+ pInfo->close_proc = NULL;
+ pInfo->switch_mode = NULL;
+ pInfo->conversion_proc = NULL;
+ pInfo->reverse_conversion_proc = NULL;
+ pInfo->fd = -1;
+ pInfo->dev = NULL;
+ pInfo->private_flags = 0;
+ pInfo->always_core_feedback = 0;
+ pInfo->conf_idev = dev;
+
+ /* Collect the options, and process the common options. */
+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL);
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ /* Mark the device configured */
+ pInfo->flags |= XI86_CONFIGURED;
+
+#ifdef XKB
+ from = X_DEFAULT;
+ if (noXkbExtension)
+ from = X_CMDLINE;
+ else if (xf86FindOption(dev->commonOptions, "XkbDisable")) {
+ noXkbExtension =
+ xf86SetBoolOption(dev->commonOptions, "XkbDisable", FALSE);
+ from = X_CONFIG;
+ }
+ if (noXkbExtension)
+ xf86Msg(from, "XKB: disabled\n");
+
+#define NULL_IF_EMPTY(s) (s[0] ? s : (xfree(s), (char *)NULL))
+
+ if (!noXkbExtension) {
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeymap", NULL))) {
+ xkbkeymap = NULL_IF_EMPTY(s);
+ xf86Msg(X_CONFIG, "XKB: keymap: \"%s\" "
+ "(overrides other XKB settings)\n", xkbkeymap);
+ } else {
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbCompat", NULL))) {
+ xkbcompat = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: compat: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbTypes", NULL))) {
+ xkbtypes = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: types: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbKeycodes", NULL))) {
+ xkbkeycodes = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: keycodes: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbGeometry", NULL))) {
+ xkbgeometry = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: geometry: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbSymbols", NULL))) {
+ xkbsymbols = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: symbols: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbRules", NULL))) {
+ xkbrules = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: rules: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbModel", NULL))) {
+ xkbmodel = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: model: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbLayout", NULL))) {
+ xkblayout = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: layout: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbVariant", NULL))) {
+ xkbvariant = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: variant: \"%s\"\n", s);
+ }
+
+ if ((s = xf86SetStrOption(dev->commonOptions, "XkbOptions", NULL))) {
+ xkboptions = NULL_IF_EMPTY(s);
+ xkbcomponents_specified = TRUE;
+ xf86Msg(X_CONFIG, "XKB: options: \"%s\"\n", s);
+ }
+ }
+ }
+#undef NULL_IF_EMPTY
+#endif
+
+ /* Return the configured device */
+ return (pInfo);
+}
+
+#ifdef XFree86LOADER
+static
+#endif
+InputDriverRec RFBKEYB = {
+ 1, /* driver version */
+ "rfbkeyb", /* driver name */
+ NULL, /* identify */
+ xf86rfbKeybInit, /* pre-init */
+ xf86rfbKeybUninit, /* un-init */
+ NULL, /* module */
+ 0 /* ref count */
+};
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+#ifdef XFree86LOADER
+static void
+xf86rfbKeybUnplug(pointer p)
+{
+}
+
+static pointer
+xf86rfbKeybPlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ xf86AddInputDriver(&RFBKEYB, module, 0);
+
+ return module;
+}
+
+void
+vncInitKeyb(void)
+{
+ xf86AddInputDriver(&RFBKEYB, NULL, 0);
+}
+
+static XF86ModuleVersionInfo xf86rfbKeybVersionRec =
+{
+ "rfbkeyb",
+ "xf4vnc Project, see http://xf4vnc.sf.net",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by */
+ /* a tool */
+};
+
+XF86ModuleData rfbkeybModuleData = {&xf86rfbKeybVersionRec,
+ xf86rfbKeybPlug,
+ xf86rfbKeybUnplug};
+
+#endif /* XFree86LOADER */
+#endif
--- xorg-server-1.7.4/hw/vnc/rfbmouse.c
+++ xorg-server-1.7.4/hw/vnc/rfbmouse.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <X11/keysym.h>
+#if XFREE86VNC
+#ifndef XFree86LOADER
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include <misc.h>
+#include <xf86.h>
+#if !defined(DGUX)
+#include <xisb.h>
+#endif
+#include <xf86Xinput.h>
+#include <exevents.h> /* Needed for InitValuator/Proximity stuff */
+#include <mipointer.h>
+
+#ifdef XFree86LOADER
+#include <xf86Module.h>
+#endif
+
+static const char *DEFAULTS[] = {
+ NULL
+};
+#else
+#include <dix.h>
+#include <mipointer.h>
+#endif
+#include "rfb.h"
+
+
+unsigned char ptrAcceleration = 50;
+
+void
+PtrDeviceOn(DeviceIntPtr pDev)
+{
+#if 0
+ ptrAcceleration = (unsigned char)pDev->ptrfeed->ctrl.num;
+#endif
+}
+
+void
+PtrDeviceInit(void)
+{
+}
+
+void
+PtrDeviceOff(void)
+{
+}
+
+
+void
+PtrDeviceControl(DeviceIntPtr dev, PtrCtrl *ctrl)
+{
+#if 0
+ ptrAcceleration = (char)ctrl->num;
+
+ if (udpSockConnected) {
+ if (write(udpSock, &ptrAcceleration, 1) <= 0) {
+ ErrorF("PtrDeviceControl: UDP input: write");
+ rfbDisconnectUDPSock();
+ }
+ }
+#endif
+}
+
+#if XFREE86VNC
+static int
+xf86rfbMouseControlProc(DeviceIntPtr device, int onoff)
+{
+ BYTE map[6];
+ DevicePtr pDev = (DevicePtr)device;
+ void *func1;
+ int (*func2)(void);
+
+ if (LoaderSymbol("GetMotionHistory"))
+ func1 = LoaderSymbol("GetMotionHistory");
+ else
+ func1 = LoaderSymbol("miPointerGetMotionEvents");
+
+ if (LoaderSymbol("GetMotionHistorySize"))
+ func2 = LoaderSymbol("GetMotionHistorySize");
+ else
+ func2 = LoaderSymbol("miPointerGetMotionBufferSize");
+
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ vncSetPointerDevice(device);
+ PtrDeviceInit();
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ map[4] = 4;
+ map[5] = 5;
+ InitPointerDeviceStruct(pDev, map, 5,
+ func1,
+ PtrDeviceControl,
+ (*func2)(), 2);
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ PtrDeviceOn(device);
+ break;
+
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ PtrDeviceOff();
+ break;
+
+ case DEVICE_CLOSE:
+ vncSetPointerDevice(NULL);
+ if (pDev->on)
+ PtrDeviceOff();
+ break;
+ }
+ return Success;
+}
+
+static void
+xf86rfbMouseUninit(InputDriverPtr drv,
+ InputInfoPtr pInfo,
+ int flags)
+{
+ xf86rfbMouseControlProc(pInfo->dev, DEVICE_OFF);
+}
+
+static InputInfoPtr
+xf86rfbMouseInit(InputDriverPtr drv,
+ IDevPtr dev,
+ int flags)
+{
+ InputInfoPtr pInfo;
+
+ if (!(pInfo = xf86AllocateInput(drv, 0)))
+ return NULL;
+
+ /* Initialise the InputInfoRec. */
+ pInfo->name = dev->identifier;
+ pInfo->type_name = "rfbMouse";
+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ pInfo->device_control = xf86rfbMouseControlProc;
+ pInfo->read_input = NULL;
+#if 0
+ pInfo->motion_history_proc = xf86GetMotionEvents;
+#endif
+ pInfo->history_size = 0;
+ pInfo->control_proc = NULL;
+ pInfo->close_proc = NULL;
+ pInfo->switch_mode = NULL;
+ pInfo->conversion_proc = NULL;
+ pInfo->reverse_conversion_proc = NULL;
+ pInfo->fd = -1;
+ pInfo->dev = NULL;
+ pInfo->private_flags = 0;
+ pInfo->always_core_feedback = 0;
+ pInfo->conf_idev = dev;
+
+ /* Collect the options, and process the common options. */
+ xf86CollectInputOptions(pInfo, DEFAULTS, NULL);
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ /* Mark the device configured */
+ pInfo->flags |= XI86_CONFIGURED;
+
+ /* Return the configured device */
+ return (pInfo);
+}
+
+#ifdef XFree86LOADER
+static
+#endif
+InputDriverRec RFBMOUSE = {
+ 1, /* driver version */
+ "rfbmouse", /* driver name */
+ NULL, /* identify */
+ xf86rfbMouseInit, /* pre-init */
+ xf86rfbMouseUninit, /* un-init */
+ NULL, /* module */
+ 0 /* ref count */
+};
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+#ifdef XFree86LOADER
+static void
+xf86rfbMouseUnplug(pointer p)
+{
+}
+
+static pointer
+xf86rfbMousePlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ xf86AddInputDriver(&RFBMOUSE, module, 0);
+
+ return module;
+}
+
+void
+vncInitMouse(void)
+{
+ xf86AddInputDriver(&RFBMOUSE, NULL, 0);
+}
+
+static XF86ModuleVersionInfo xf86rfbMouseVersionRec =
+{
+ "rfbmouse",
+ "xf4vnc Project, see http://xf4vnc.sf.net",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by */
+ /* a tool */
+};
+
+XF86ModuleData rfbmouseModuleData = {&xf86rfbMouseVersionRec,
+ xf86rfbMousePlug,
+ xf86rfbMouseUnplug};
+
+#endif /* XFree86LOADER */
+#endif
--- xorg-server-1.7.4/hw/vnc/rfbproto.h
+++ xorg-server-1.7.4/hw/vnc/rfbproto.h
@@ -0,0 +1,1362 @@
+/*
+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+ * rfbproto.h - header file for the RFB protocol, versions 3.3, 3.7 and 3.7t
+ * (protocol 3.7t is effectively 3.7 with TightVNC extensions enabled)
+ *
+ * Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
+ * integer (for n = 8, 16 and 32).
+ *
+ * All multiple byte integers are in big endian (network) order (most
+ * significant byte first). Unless noted otherwise there is no special
+ * alignment of protocol structures.
+ *
+ *
+ * Once the initial handshaking is done, all messages start with a type byte,
+ * (usually) followed by message-specific data. The order of definitions in
+ * this file is as follows:
+ *
+ * (1) Structures used in several types of message.
+ * (2) Structures used in the initial handshaking.
+ * (3) Message types.
+ * (4) Encoding types.
+ * (5) For each message type, the form of the data following the type byte.
+ * Sometimes this is defined by a single structure but the more complex
+ * messages have to be explained by comments.
+ */
+
+
+/*****************************************************************************
+ *
+ * Structures used in several messages
+ *
+ *****************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * Structure used to specify a rectangle. This structure is a multiple of 4
+ * bytes so that it can be interspersed with 32-bit pixel data without
+ * affecting alignment.
+ */
+
+typedef struct _rfbRectangle {
+ CARD16 x;
+ CARD16 y;
+ CARD16 w;
+ CARD16 h;
+} rfbRectangle;
+
+#define sz_rfbRectangle 8
+
+
+/*-----------------------------------------------------------------------------
+ * Structure used to specify pixel format.
+ */
+
+typedef struct _rfbPixelFormat {
+
+ CARD8 bitsPerPixel; /* 8,16,32 only */
+
+ CARD8 depth; /* 8 to 32 */
+
+ CARD8 bigEndian; /* True if multi-byte pixels are interpreted
+ as big endian, or if single-bit-per-pixel
+ has most significant bit of the byte
+ corresponding to first (leftmost) pixel. Of
+ course this is meaningless for 8 bits/pix */
+
+ CARD8 trueColour; /* If false then we need a "colour map" to
+ convert pixels to RGB. If true, xxxMax and
+ xxxShift specify bits used for red, green
+ and blue */
+
+ /* the following fields are only meaningful if trueColour is true */
+
+ CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the
+ number of bits used for red). Note this
+ value is always in big endian order. */
+
+ CARD16 greenMax; /* similar for green */
+
+ CARD16 blueMax; /* and blue */
+
+ CARD8 redShift; /* number of shifts needed to get the red
+ value in a pixel to the least significant
+ bit. To find the red value from a given
+ pixel, do the following:
+ 1) Swap pixel value according to bigEndian
+ (e.g. if bigEndian is false and host byte
+ order is big endian, then swap).
+ 2) Shift right by redShift.
+ 3) AND with redMax (in host byte order).
+ 4) You now have the red value between 0 and
+ redMax. */
+
+ CARD8 greenShift; /* similar for green */
+
+ CARD8 blueShift; /* and blue */
+
+ CARD8 pad1;
+ CARD16 pad2;
+
+} rfbPixelFormat;
+
+#define sz_rfbPixelFormat 16
+
+
+/*-----------------------------------------------------------------------------
+ * Structure used to describe protocol options such as tunneling methods,
+ * authentication schemes and message types (protocol version 3.7t).
+ */
+
+typedef struct _rfbCapabilityInfo {
+
+ CARD32 code; /* numeric identifier */
+ CARD8 vendorSignature[4]; /* vendor identification */
+ CARD8 nameSignature[8]; /* abbreviated option name */
+
+} rfbCapabilityInfo;
+
+#define sz_rfbCapabilityInfoVendor 4
+#define sz_rfbCapabilityInfoName 8
+#define sz_rfbCapabilityInfo 16
+
+/*
+ * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC.
+ */
+
+#define rfbStandardVendor "STDV"
+#define rfbTridiaVncVendor "TRDV"
+#define rfbTightVncVendor "TGHT"
+#define rfbTungstenGraphicsVendor "TGIV"
+
+
+/*****************************************************************************
+ *
+ * Initial handshaking messages
+ *
+ *****************************************************************************/
+
+/*-----------------------------------------------------------------------------
+ * Protocol Version
+ *
+ * The server always sends 12 bytes to start which identifies the latest RFB
+ * protocol version number which it supports. These bytes are interpreted
+ * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where
+ * xxx and yyy are the major and minor version numbers (for version 3.7
+ * this is "RFB 003.007\n").
+ *
+ * The client then replies with a similar 12-byte message giving the version
+ * number of the protocol which should actually be used (which may be different
+ * to that quoted by the server).
+ *
+ * It is intended that both clients and servers may provide some level of
+ * backwards compatibility by this mechanism. Servers in particular should
+ * attempt to provide backwards compatibility, and even forwards compatibility
+ * to some extent. For example if a client demands version 3.1 of the
+ * protocol, a 3.0 server can probably assume that by ignoring requests for
+ * encoding types it doesn't understand, everything will still work OK. This
+ * will probably not be the case for changes in the major version number.
+ *
+ * The format string below can be used in sprintf or sscanf to generate or
+ * decode the version string respectively.
+ */
+
+#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
+#define rfbProtocolMajorVersion 3
+#define rfbProtocolMinorVersion 7
+#define rfbProtocolFallbackMinorVersion 3
+
+typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
+
+#define sz_rfbProtocolVersionMsg 12
+
+
+/*
+ * Negotiation of the security type (protocol version 3.7)
+ *
+ * Once the protocol version has been decided, the server either sends a list
+ * of supported security types, or informs the client about an error (when the
+ * number of security types is 0). Security type rfbSecTypeTight is used to
+ * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth
+ * stands for classic VNC authentication.
+ *
+ * The client selects a particular security type from the list provided by the
+ * server.
+ */
+
+#define rfbSecTypeInvalid 0
+#define rfbSecTypeNone 1
+#define rfbSecTypeVncAuth 2
+#define rfbSecTypeTight 16
+
+
+/*-----------------------------------------------------------------------------
+ * Negotiation of Tunneling Capabilities (protocol version 3.7t)
+ *
+ * If the chosen security type is rfbSecTypeTight, the server sends a list of
+ * supported tunneling methods ("tunneling" refers to any additional layer of
+ * data transformation, such as encryption or external compression.)
+ *
+ * nTunnelTypes specifies the number of following rfbCapabilityInfo structures
+ * that list all supported tunneling methods in the order of preference.
+ *
+ * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be
+ * used, and the client should not send a response requesting a tunneling
+ * method.
+ */
+
+typedef struct _rfbTunnelingCapsMsg {
+ CARD32 nTunnelTypes;
+ /* followed by nTunnelTypes * rfbCapabilityInfo structures */
+} rfbTunnelingCapsMsg;
+
+#define sz_rfbTunnelingCapsMsg 4
+
+/*-----------------------------------------------------------------------------
+ * Tunneling Method Request (protocol version 3.7t)
+ *
+ * If the list of tunneling capabilities sent by the server was not empty, the
+ * client should reply with a 32-bit code specifying a particular tunneling
+ * method. The following code should be used for no tunneling.
+ */
+
+#define rfbNoTunneling 0
+#define sig_rfbNoTunneling "NOTUNNEL"
+
+
+/*-----------------------------------------------------------------------------
+ * Negotiation of Authentication Capabilities (protocol version 3.7t)
+ *
+ * After setting up tunneling, the server sends a list of supported
+ * authentication schemes.
+ *
+ * nAuthTypes specifies the number of following rfbCapabilityInfo structures
+ * that list all supported authentication schemes in the order of preference.
+ *
+ * NOTE: If nAuthTypes is 0, that tells the client that no authentication is
+ * necessary, and the client should not send a response requesting an
+ * authentication scheme.
+ */
+
+typedef struct _rfbAuthenticationCapsMsg {
+ CARD32 nAuthTypes;
+ /* followed by nAuthTypes * rfbCapabilityInfo structures */
+} rfbAuthenticationCapsMsg;
+
+#define sz_rfbAuthenticationCapsMsg 4
+
+/*-----------------------------------------------------------------------------
+ * Authentication Scheme Request (protocol version 3.7t)
+ *
+ * If the list of authentication capabilities sent by the server was not empty,
+ * the client should reply with a 32-bit code specifying a particular
+ * authentication scheme. The following codes are supported.
+ */
+
+#define rfbAuthNone 1
+#define rfbAuthVNC 2
+#define rfbAuthUnixLogin 129
+#define rfbAuthExternal 130
+
+#define sig_rfbAuthNone "NOAUTH__"
+#define sig_rfbAuthVNC "VNCAUTH_"
+#define sig_rfbAuthUnixLogin "ULGNAUTH"
+#define sig_rfbAuthExternal "XTRNAUTH"
+
+
+/*-----------------------------------------------------------------------------
+ * Standard VNC Authentication (all protocol versions)
+ *
+ * Standard authentication result codes are defined below.
+ */
+
+#define rfbVncAuthOK 0
+#define rfbVncAuthFailed 1
+#define rfbVncAuthTooMany 2
+
+
+/*-----------------------------------------------------------------------------
+ * Client Initialisation Message
+ *
+ * Once the client and server are sure that they're happy to talk to one
+ * another, the client sends an initialisation message. At present this
+ * message only consists of a boolean indicating whether the server should try
+ * to share the desktop by leaving other clients connected, or give exclusive
+ * access to this client by disconnecting all other clients.
+ */
+
+typedef struct _rfbClientInitMsg {
+ CARD8 shared;
+} rfbClientInitMsg;
+
+#define sz_rfbClientInitMsg 1
+
+
+/*-----------------------------------------------------------------------------
+ * Server Initialisation Message
+ *
+ * After the client initialisation message, the server sends one of its own.
+ * This tells the client the width and height of the server's framebuffer,
+ * its pixel format and the name associated with the desktop.
+ */
+
+typedef struct _rfbServerInitMsg {
+ CARD16 framebufferWidth;
+ CARD16 framebufferHeight;
+ rfbPixelFormat format; /* the server's preferred pixel format */
+ CARD32 nameLength;
+ /* followed by char name[nameLength] */
+} rfbServerInitMsg;
+
+#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat)
+
+
+/*-----------------------------------------------------------------------------
+ * Server Interaction Capabilities Message (protocol version 3.7t)
+ *
+ * In the protocol version 3.7t, the server informs the client what message
+ * types it supports in addition to ones defined in the protocol version 3.7.
+ * Also, the server sends the list of all supported encodings (note that it's
+ * not necessary to advertise the "raw" encoding sinse it MUST be supported in
+ * RFB 3.x protocols).
+ *
+ * This data immediately follows the server initialisation message.
+ */
+
+typedef struct _rfbInteractionCapsMsg {
+ CARD16 nServerMessageTypes;
+ CARD16 nClientMessageTypes;
+ CARD16 nEncodingTypes;
+ CARD16 pad; /* reserved, must be 0 */
+ /* followed by nServerMessageTypes * rfbCapabilityInfo structures */
+ /* followed by nClientMessageTypes * rfbCapabilityInfo structures */
+} rfbInteractionCapsMsg;
+
+#define sz_rfbInteractionCapsMsg 8
+
+
+/*
+ * Following the server initialisation message it's up to the client to send
+ * whichever protocol messages it wants. Typically it will send a
+ * SetPixelFormat message and a SetEncodings message, followed by a
+ * FramebufferUpdateRequest. From then on the server will send
+ * FramebufferUpdate messages in response to the client's
+ * FramebufferUpdateRequest messages. The client should send
+ * FramebufferUpdateRequest messages with incremental set to true when it has
+ * finished processing one FramebufferUpdate and is ready to process another.
+ * With a fast client, the rate at which FramebufferUpdateRequests are sent
+ * should be regulated to avoid hogging the network.
+ */
+
+
+
+/*****************************************************************************
+ *
+ * Message types
+ *
+ *****************************************************************************/
+
+/* server -> client */
+
+#define rfbFramebufferUpdate 0
+#define rfbSetColourMapEntries 1
+#define rfbBell 2
+#define rfbServerCutText 3
+/* Chromium extensions, use higher values */
+#define rfbChromiumStart 50
+#define rfbChromiumMoveResizeWindow 51
+#define rfbChromiumClipList 52
+#define rfbChromiumWindowShow 53
+#define rfbChromiumWindowDestroy 54
+
+#define rfbFileListData 130
+#define rfbFileDownloadData 131
+#define rfbFileUploadCancel 132
+#define rfbFileDownloadFailed 133
+
+/* signatures for non-standard messages */
+#define sig_rfbFileListData "FTS_LSDT"
+#define sig_rfbFileDownloadData "FTS_DNDT"
+#define sig_rfbFileUploadCancel "FTS_UPCN"
+#define sig_rfbFileDownloadFailed "FTS_DNFL"
+
+
+/* client -> server */
+
+#define rfbSetPixelFormat 0
+#define rfbFixColourMapEntries 1 /* not currently supported */
+#define rfbSetEncodings 2
+#define rfbFramebufferUpdateRequest 3
+#define rfbKeyEvent 4
+#define rfbPointerEvent 5
+#define rfbClientCutText 6
+/* Chromium extensions, use higher values */
+#define rfbChromiumStop 50
+#define rfbChromiumExpose 51
+
+#define rfbFileListRequest 130
+#define rfbFileDownloadRequest 131
+#define rfbFileUploadRequest 132
+#define rfbFileUploadData 133
+#define rfbFileDownloadCancel 134
+#define rfbFileUploadFailed 135
+#define rfbFileCreateDirRequest 136
+
+/* signatures for non-standard messages */
+#define sig_rfbFileListRequest "FTC_LSRQ"
+#define sig_rfbFileDownloadRequest "FTC_DNRQ"
+#define sig_rfbFileUploadRequest "FTC_UPRQ"
+#define sig_rfbFileUploadData "FTC_UPDT"
+#define sig_rfbFileDownloadCancel "FTC_DNCN"
+#define sig_rfbFileUploadFailed "FTC_UPFL"
+#define sig_rfbFileCreateDirRequest "FTC_FCDR"
+
+/*****************************************************************************
+ *
+ * Encoding types
+ *
+ *****************************************************************************/
+
+#define rfbEncodingRaw 0
+#define rfbEncodingCopyRect 1
+#define rfbEncodingRRE 2
+#define rfbEncodingCoRRE 4
+#define rfbEncodingHextile 5
+#define rfbEncodingZlib 6
+#define rfbEncodingTight 7
+#define rfbEncodingZlibHex 8
+
+/* signatures for basic encoding types */
+#define sig_rfbEncodingRaw "RAW_____"
+#define sig_rfbEncodingCopyRect "COPYRECT"
+#define sig_rfbEncodingRRE "RRE_____"
+#define sig_rfbEncodingCoRRE "CORRE___"
+#define sig_rfbEncodingHextile "HEXTILE_"
+#define sig_rfbEncodingZlib "ZLIB____"
+#define sig_rfbEncodingTight "TIGHT___"
+#define sig_rfbEncodingZlibHex "ZLIBHEX_"
+#define sig_rfbEncodingChromium "CHROMIUM"
+
+/*
+ * Special encoding numbers:
+ * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
+ * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data;
+ * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions;
+ * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet;
+ * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor;
+ * 0xFFFFFFF0 .. 0xFFFFFFFF -- not allocated yet.
+ */
+
+#define rfbEncodingCompressLevel0 0xFFFFFF00
+#define rfbEncodingCompressLevel1 0xFFFFFF01
+#define rfbEncodingCompressLevel2 0xFFFFFF02
+#define rfbEncodingCompressLevel3 0xFFFFFF03
+#define rfbEncodingCompressLevel4 0xFFFFFF04
+#define rfbEncodingCompressLevel5 0xFFFFFF05
+#define rfbEncodingCompressLevel6 0xFFFFFF06
+#define rfbEncodingCompressLevel7 0xFFFFFF07
+#define rfbEncodingCompressLevel8 0xFFFFFF08
+#define rfbEncodingCompressLevel9 0xFFFFFF09
+
+#define rfbEncodingXCursor 0xFFFFFF10
+#define rfbEncodingRichCursor 0xFFFFFF11
+#define rfbEncodingPointerPos 0xFFFFFF18
+
+#define rfbEncodingLastRect 0xFFFFFF20
+#define rfbEncodingNewFBSize 0xFFFFFF21
+#define rfbEncodingChromium 0xFFFFFF2F
+#define rfbEncodingChromium2 0xFFFFFF30
+
+#define rfbEncodingQualityLevel0 0xFFFFFFE0
+#define rfbEncodingQualityLevel1 0xFFFFFFE1
+#define rfbEncodingQualityLevel2 0xFFFFFFE2
+#define rfbEncodingQualityLevel3 0xFFFFFFE3
+#define rfbEncodingQualityLevel4 0xFFFFFFE4
+#define rfbEncodingQualityLevel5 0xFFFFFFE5
+#define rfbEncodingQualityLevel6 0xFFFFFFE6
+#define rfbEncodingQualityLevel7 0xFFFFFFE7
+#define rfbEncodingQualityLevel8 0xFFFFFFE8
+#define rfbEncodingQualityLevel9 0xFFFFFFE9
+
+/* signatures for "fake" encoding types */
+#define sig_rfbEncodingCompressLevel0 "COMPRLVL"
+#define sig_rfbEncodingXCursor "X11CURSR"
+#define sig_rfbEncodingRichCursor "RCHCURSR"
+#define sig_rfbEncodingPointerPos "POINTPOS"
+#define sig_rfbEncodingLastRect "LASTRECT"
+#define sig_rfbEncodingNewFBSize "NEWFBSIZ"
+#define sig_rfbEncodingQualityLevel0 "JPEGQLVL"
+
+
+/*****************************************************************************
+ *
+ * Server -> client message definitions
+ *
+ *****************************************************************************/
+
+
+/*-----------------------------------------------------------------------------
+ * FramebufferUpdate - a block of rectangles to be copied to the framebuffer.
+ *
+ * This message consists of a header giving the number of rectangles of pixel
+ * data followed by the rectangles themselves. The header is padded so that
+ * together with the type byte it is an exact multiple of 4 bytes (to help
+ * with alignment of 32-bit pixels):
+ */
+
+typedef struct _rfbFramebufferUpdateMsg {
+ CARD8 type; /* always rfbFramebufferUpdate */
+ CARD8 pad;
+ CARD16 nRects;
+ /* followed by nRects rectangles */
+} rfbFramebufferUpdateMsg;
+
+#define sz_rfbFramebufferUpdateMsg 4
+
+/*
+ * Each rectangle of pixel data consists of a header describing the position
+ * and size of the rectangle and a type word describing the encoding of the
+ * pixel data, followed finally by the pixel data. Note that if the client has
+ * not sent a SetEncodings message then it will only receive raw pixel data.
+ * Also note again that this structure is a multiple of 4 bytes.
+ */
+
+typedef struct _rfbFramebufferUpdateRectHeader {
+ rfbRectangle r;
+ CARD32 encoding; /* one of the encoding types rfbEncoding... */
+} rfbFramebufferUpdateRectHeader;
+
+#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4)
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Raw Encoding. Pixels are sent in top-to-bottom scanline order,
+ * left-to-right within a scanline with no padding in between.
+ */
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * CopyRect Encoding. The pixels are specified simply by the x and y position
+ * of the source rectangle.
+ */
+
+typedef struct _rfbCopyRect {
+ CARD16 srcX;
+ CARD16 srcY;
+} rfbCopyRect;
+
+#define sz_rfbCopyRect 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure
+ * giving the number of subrectangles following. Finally the data follows in
+ * the form [<bgpixel><subrect><subrect>...] where each <subrect> is
+ * [<pixel><rfbRectangle>].
+ */
+
+typedef struct _rfbRREHeader {
+ CARD32 nSubrects;
+} rfbRREHeader;
+
+#define sz_rfbRREHeader 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving
+ * the number of subrectangles following. Finally the data follows in the form
+ * [<bgpixel><subrect><subrect>...] where each <subrect> is
+ * [<pixel><rfbCoRRERectangle>]. This means that
+ * the whole rectangle must be at most 255x255 pixels.
+ */
+
+typedef struct _rfbCoRRERectangle {
+ CARD8 x;
+ CARD8 y;
+ CARD8 w;
+ CARD8 h;
+} rfbCoRRERectangle;
+
+#define sz_rfbCoRRERectangle 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels,
+ * starting at the top left going in left-to-right, top-to-bottom order. If
+ * the width of the rectangle is not an exact multiple of 16 then the width of
+ * the last tile in each row will be correspondingly smaller. Similarly if the
+ * height is not an exact multiple of 16 then the height of each tile in the
+ * final row will also be smaller. Each tile begins with a "subencoding" type
+ * byte, which is a mask made up of a number of bits. If the Raw bit is set
+ * then the other bits are irrelevant; w*h pixel values follow (where w and h
+ * are the width and height of the tile). Otherwise the tile is encoded in a
+ * similar way to RRE, except that the position and size of each subrectangle
+ * can be specified in just two bytes. The other bits in the mask are as
+ * follows:
+ *
+ * BackgroundSpecified - if set, a pixel value follows which specifies
+ * the background colour for this tile. The first non-raw tile in a
+ * rectangle must have this bit set. If this bit isn't set then the
+ * background is the same as the last tile.
+ *
+ * ForegroundSpecified - if set, a pixel value follows which specifies
+ * the foreground colour to be used for all subrectangles in this tile.
+ * If this bit is set then the SubrectsColoured bit must be zero.
+ *
+ * AnySubrects - if set, a single byte follows giving the number of
+ * subrectangles following. If not set, there are no subrectangles (i.e.
+ * the whole tile is just solid background colour).
+ *
+ * SubrectsColoured - if set then each subrectangle is preceded by a pixel
+ * value giving the colour of that subrectangle. If not set, all
+ * subrectangles are the same colour, the foreground colour; if the
+ * ForegroundSpecified bit wasn't set then the foreground is the same as
+ * the last tile.
+ *
+ * The position and size of each subrectangle is specified in two bytes. The
+ * Pack macros below can be used to generate the two bytes from x, y, w, h,
+ * and the Extract macros can be used to extract the x, y, w, h values from
+ * the two bytes.
+ */
+
+#define rfbHextileRaw (1 << 0)
+#define rfbHextileBackgroundSpecified (1 << 1)
+#define rfbHextileForegroundSpecified (1 << 2)
+#define rfbHextileAnySubrects (1 << 3)
+#define rfbHextileSubrectsColoured (1 << 4)
+
+#define rfbHextilePackXY(x,y) (((x) << 4) | (y))
+#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1))
+#define rfbHextileExtractX(byte) ((byte) >> 4)
+#define rfbHextileExtractY(byte) ((byte) & 0xf)
+#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
+#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * ZLIB - zlib compression Encoding. We have an rfbZlibHeader structure
+ * giving the number of bytes to follow. Finally the data follows in
+ * zlib compressed format.
+ */
+
+typedef struct _rfbZlibHeader {
+ CARD32 nBytes;
+} rfbZlibHeader;
+
+#define sz_rfbZlibHeader 4
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Tight Encoding.
+ *
+ *-- The first byte of each Tight-encoded rectangle is a "compression control
+ * byte". Its format is as follows (bit 0 is the least significant one):
+ *
+ * bit 0: if 1, then compression stream 0 should be reset;
+ * bit 1: if 1, then compression stream 1 should be reset;
+ * bit 2: if 1, then compression stream 2 should be reset;
+ * bit 3: if 1, then compression stream 3 should be reset;
+ * bits 7-4: if 1000 (0x08), then the compression type is "fill",
+ * if 1001 (0x09), then the compression type is "jpeg",
+ * if 0xxx, then the compression type is "basic",
+ * values greater than 1001 are not valid.
+ *
+ * If the compression type is "basic", then bits 6..4 of the
+ * compression control byte (those xxx in 0xxx) specify the following:
+ *
+ * bits 5-4: decimal representation is the index of a particular zlib
+ * stream which should be used for decompressing the data;
+ * bit 6: if 1, then a "filter id" byte is following this byte.
+ *
+ *-- The data that follows after the compression control byte described
+ * above depends on the compression type ("fill", "jpeg" or "basic").
+ *
+ *-- If the compression type is "fill", then the only pixel value follows, in
+ * client pixel format (see NOTE 1). This value applies to all pixels of the
+ * rectangle.
+ *
+ *-- If the compression type is "jpeg", the following data stream looks like
+ * this:
+ *
+ * 1..3 bytes: data size (N) in compact representation;
+ * N bytes: JPEG image.
+ *
+ * Data size is compactly represented in one, two or three bytes, according
+ * to the following scheme:
+ *
+ * 0xxxxxxx (for values 0..127)
+ * 1xxxxxxx 0yyyyyyy (for values 128..16383)
+ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303)
+ *
+ * Here each character denotes one bit, xxxxxxx are the least significant 7
+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the
+ * most significant 8 bits (bits 14-21). For example, decimal value 10000
+ * should be represented as two bytes: binary 10010000 01001110, or
+ * hexadecimal 90 4E.
+ *
+ *-- If the compression type is "basic" and bit 6 of the compression control
+ * byte was set to 1, then the next (second) byte specifies "filter id" which
+ * tells the decoder what filter type was used by the encoder to pre-process
+ * pixel data before the compression. The "filter id" byte can be one of the
+ * following:
+ *
+ * 0: no filter ("copy" filter);
+ * 1: "palette" filter;
+ * 2: "gradient" filter.
+ *
+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id"
+ * byte), or if the filter id is 0, then raw pixel values in the client
+ * format (see NOTE 1) will be compressed. See below details on the
+ * compression.
+ *
+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm
+ * which converts each color component to a difference between a "predicted"
+ * intensity and the actual intensity. Such a technique does not affect
+ * uncompressed data size, but helps to compress photo-like images better.
+ * Pseudo-code for converting intensities to differences is the following:
+ *
+ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1];
+ * if (P[i,j] < 0) then P[i,j] := 0;
+ * if (P[i,j] > MAX) then P[i,j] := MAX;
+ * D[i,j] := V[i,j] - P[i,j];
+ *
+ * Here V[i,j] is the intensity of a color component for a pixel at
+ * coordinates (i,j). MAX is the maximum value of intensity for a color
+ * component.
+ *
+ *-- The "palette" filter converts true-color pixel data to indexed colors
+ * and a palette which can consist of 2..256 colors. If the number of colors
+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to
+ * encode one pixel. 1-bit encoding is performed such way that the most
+ * significant bits correspond to the leftmost pixels, and each raw of pixels
+ * is aligned to the byte boundary. When "palette" filter is used, the
+ * palette is sent before the pixel data. The palette begins with an unsigned
+ * byte which value is the number of colors in the palette minus 1 (i.e. 1
+ * means 2 colors, 255 means 256 colors in the palette). Then follows the
+ * palette itself which consist of pixel values in client pixel format (see
+ * NOTE 1).
+ *
+ *-- The pixel data is compressed using the zlib library. But if the data
+ * size after applying the filter but before the compression is less then 12,
+ * then the data is sent as is, uncompressed. Four separate zlib streams
+ * (0..3) can be used and the decoder should read the actual stream id from
+ * the compression control byte (see NOTE 2).
+ *
+ * If the compression is not used, then the pixel data is sent as is,
+ * otherwise the data stream looks like this:
+ *
+ * 1..3 bytes: data size (N) in compact representation;
+ * N bytes: zlib-compressed data.
+ *
+ * Data size is compactly represented in one, two or three bytes, just like
+ * in the "jpeg" compression method (see above).
+ *
+ *-- NOTE 1. If the color depth is 24, and all three color components are
+ * 8-bit wide, then one pixel in Tight encoding is always represented by
+ * three bytes, where the first byte is red component, the second byte is
+ * green component, and the third byte is blue component of the pixel color
+ * value. This applies to colors in palettes as well.
+ *
+ *-- NOTE 2. The decoder must reset compression streams' states before
+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control
+ * byte are set to 1. Note that the decoder must reset zlib streams even if
+ * the compression type is "fill" or "jpeg".
+ *
+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
+ * when bits-per-pixel value is either 16 or 32, not 8.
+ *
+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048
+ * pixels. If a rectangle is wider, it must be split into several rectangles
+ * and each one should be encoded separately.
+ *
+ */
+
+#define rfbTightExplicitFilter 0x04
+#define rfbTightFill 0x08
+#define rfbTightJpeg 0x09
+#define rfbTightMaxSubencoding 0x09
+
+/* Filters to improve compression efficiency */
+#define rfbTightFilterCopy 0x00
+#define rfbTightFilterPalette 0x01
+#define rfbTightFilterGradient 0x02
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the
+ * hextile encoding with zlib compression on the tiles that can not be
+ * efficiently encoded with one of the other hextile subencodings. The
+ * new zlib subencoding uses two bytes to specify the length of the
+ * compressed tile and then the compressed data follows. As with the
+ * raw sub-encoding, the zlib subencoding invalidates the other
+ * values, if they are also set.
+ */
+
+#define rfbHextileZlibRaw (1 << 5)
+#define rfbHextileZlibHex (1 << 6)
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * XCursor encoding. This is a special encoding used to transmit X-style
+ * cursor shapes from server to clients. Note that for this encoding,
+ * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot
+ * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB
+ * samples are sent after header in the rfbXCursorColors structure. They
+ * denote foreground and background colors of the cursor. If a client
+ * supports only black-and-white cursors, it should ignore these colors and
+ * assume that foreground is black and background is white. Next, two bitmaps
+ * (1 bits per pixel) follow: first one with actual data (value 0 denotes
+ * background color, value 1 denotes foreground color), second one with
+ * transparency data (bits with zero value mean that these pixels are
+ * transparent). Both bitmaps represent cursor data in a byte stream, from
+ * left to right, from top to bottom, and each row is byte-aligned. Most
+ * significant bits correspond to leftmost pixels. The number of bytes in
+ * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor
+ * should be hidden (or default local cursor should be set by the client).
+ */
+
+typedef struct _rfbXCursorColors {
+ CARD8 foreRed;
+ CARD8 foreGreen;
+ CARD8 foreBlue;
+ CARD8 backRed;
+ CARD8 backGreen;
+ CARD8 backBlue;
+} rfbXCursorColors;
+
+#define sz_rfbXCursorColors 6
+
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * RichCursor encoding. This is a special encoding used to transmit cursor
+ * shapes from server to clients. It is similar to the XCursor encoding but
+ * uses client pixel format instead of two RGB colors to represent cursor
+ * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader
+ * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h).
+ * After header, two pixmaps follow: first one with cursor image in current
+ * client pixel format (like in raw encoding), second with transparency data
+ * (1 bit per pixel, exactly the same format as used for transparency bitmap
+ * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or
+ * default local cursor should be set by the client).
+ */
+
+
+/*-----------------------------------------------------------------------------
+ * SetColourMapEntries - these messages are only sent if the pixel
+ * format uses a "colour map" (i.e. trueColour false) and the client has not
+ * fixed the entire colour map using FixColourMapEntries. In addition they
+ * will only start being sent after the client has sent its first
+ * FramebufferUpdateRequest. So if the client always tells the server to use
+ * trueColour then it never needs to process this type of message.
+ */
+
+typedef struct _rfbSetColourMapEntriesMsg {
+ CARD8 type; /* always rfbSetColourMapEntries */
+ CARD8 redIndex; /* used to be pad, but used for DirectColor */
+ CARD16 firstColour;
+ CARD16 nColours;
+
+ /* Followed by nColours * 3 * CARD16
+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
+
+} rfbSetColourMapEntriesMsg;
+
+#define sz_rfbSetColourMapEntriesMsg 6
+
+
+
+/*-----------------------------------------------------------------------------
+ * Bell - ring a bell on the client if it has one.
+ */
+
+typedef struct _rfbBellMsg {
+ CARD8 type; /* always rfbBell */
+} rfbBellMsg;
+
+#define sz_rfbBellMsg 1
+
+
+
+/*-----------------------------------------------------------------------------
+ * ServerCutText - the server has new text in its cut buffer.
+ */
+
+typedef struct _rfbServerCutTextMsg {
+ CARD8 type; /* always rfbServerCutText */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 length;
+ /* followed by char text[length] */
+} rfbServerCutTextMsg;
+
+#define sz_rfbServerCutTextMsg 8
+
+/*-----------------------------------------------------------------------------
+ * ChromiumStart - a port number for the crserver
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumStart */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 crServerPort;
+ CARD32 mothershipPort;
+} rfbChromiumStartMsg;
+
+#define sz_rfbChromiumStartMsg 12
+
+
+/*-----------------------------------------------------------------------------
+ * ChromiumMoveResizeWindow - move a chromium window
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumMoveResizeWindow */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 winid;
+ CARD32 x;
+ CARD32 y;
+ CARD32 w;
+ CARD32 h;
+} rfbChromiumMoveResizeWindowMsg;
+
+#define sz_rfbChromiumMoveResizeWindowMsg 24
+
+/*-----------------------------------------------------------------------------
+ * ChromiumClipList - send clip list
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumClipList */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 winid;
+ CARD32 length;
+} rfbChromiumClipListMsg;
+
+#define sz_rfbChromiumClipListMsg 12
+
+/*-----------------------------------------------------------------------------
+ * ChromiumWindowShow - map or unmap a window
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumWindowShow */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 winid;
+ CARD32 show;
+} rfbChromiumWindowShowMsg;
+
+#define sz_rfbChromiumWindowShowMsg 12
+
+/*-----------------------------------------------------------------------------
+ * ChromiumWindowDestroy - destroy a window
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumWindowDestroy */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 winid;
+} rfbChromiumWindowDestroyMsg;
+
+#define sz_rfbChromiumWindowDestroyMsg 8
+
+/*-----------------------------------------------------------------------------
+ * FileListData
+ */
+
+typedef struct _rfbFileListDataMsg {
+ CARD8 type;
+ CARD8 flags;
+ CARD16 numFiles;
+ CARD16 dataSize;
+ CARD16 compressedSize;
+ /* Followed by SizeData[numFiles] */
+ /* Followed by Filenames[compressedSize] */
+} rfbFileListDataMsg;
+
+#define sz_rfbFileListDataMsg 8
+
+/*-----------------------------------------------------------------------------
+ * FileDownloadData
+ */
+
+typedef struct _rfbFileDownloadDataMsg {
+ CARD8 type;
+ CARD8 compressLevel;
+ CARD16 realSize;
+ CARD16 compressedSize;
+ /* Followed by File[copressedSize] */
+} rfbFileDownloadDataMsg;
+
+#define sz_rfbFileDownloadDataMsg 6
+
+
+/*-----------------------------------------------------------------------------
+ * FileUploadCancel
+ */
+
+typedef struct _rfbFileUploadCancelMsg {
+ CARD8 type;
+ CARD8 unused;
+ CARD16 reasonLen;
+ /* Followed by reason[reasonLen] */
+} rfbFileUploadCancelMsg;
+
+#define sz_rfbFileUploadCancelMsg 4
+
+/*-----------------------------------------------------------------------------
+ * FileDownloadFailed
+ */
+
+typedef struct _rfbFileDownloadFailedMsg {
+ CARD8 type;
+ CARD8 unused;
+ CARD16 reasonLen;
+ /* Followed by reason[reasonLen] */
+} rfbFileDownloadFailedMsg;
+
+#define sz_rfbFileDownloadFailedMsg 4
+
+/*-----------------------------------------------------------------------------
+ * Union of all server->client messages.
+ */
+
+typedef union _rfbServerToClientMsg {
+ CARD8 type;
+ rfbFramebufferUpdateMsg fu;
+ rfbSetColourMapEntriesMsg scme;
+ rfbBellMsg b;
+ rfbServerCutTextMsg sct;
+ rfbFileListDataMsg fld;
+ rfbFileDownloadDataMsg fdd;
+ rfbFileUploadCancelMsg fuc;
+ rfbFileDownloadFailedMsg fdf;
+ rfbChromiumStartMsg scd;
+ rfbChromiumMoveResizeWindowMsg scm;
+ rfbChromiumClipListMsg sccl;
+ rfbChromiumWindowShowMsg scws;
+ rfbChromiumWindowDestroyMsg scwd;
+} rfbServerToClientMsg;
+
+
+
+/*****************************************************************************
+ *
+ * Message definitions (client -> server)
+ *
+ *****************************************************************************/
+
+
+/*-----------------------------------------------------------------------------
+ * SetPixelFormat - tell the RFB server the format in which the client wants
+ * pixels sent.
+ */
+
+typedef struct _rfbSetPixelFormatMsg {
+ CARD8 type; /* always rfbSetPixelFormat */
+ CARD8 pad1;
+ CARD16 pad2;
+ rfbPixelFormat format;
+} rfbSetPixelFormatMsg;
+
+#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4)
+
+
+/*-----------------------------------------------------------------------------
+ * FixColourMapEntries - when the pixel format uses a "colour map", fix
+ * read-only colour map entries.
+ *
+ * ***************** NOT CURRENTLY SUPPORTED *****************
+ */
+
+typedef struct _rfbFixColourMapEntriesMsg {
+ CARD8 type; /* always rfbFixColourMapEntries */
+ CARD8 pad;
+ CARD16 firstColour;
+ CARD16 nColours;
+
+ /* Followed by nColours * 3 * CARD16
+ r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
+
+} rfbFixColourMapEntriesMsg;
+
+#define sz_rfbFixColourMapEntriesMsg 6
+
+
+/*-----------------------------------------------------------------------------
+ * SetEncodings - tell the RFB server which encoding types we accept. Put them
+ * in order of preference, if we have any. We may always receive raw
+ * encoding, even if we don't specify it here.
+ */
+
+typedef struct _rfbSetEncodingsMsg {
+ CARD8 type; /* always rfbSetEncodings */
+ CARD8 pad;
+ CARD16 nEncodings;
+ /* followed by nEncodings * CARD32 encoding types */
+} rfbSetEncodingsMsg;
+
+#define sz_rfbSetEncodingsMsg 4
+
+
+/*-----------------------------------------------------------------------------
+ * FramebufferUpdateRequest - request for a framebuffer update. If incremental
+ * is true then the client just wants the changes since the last update. If
+ * false then it wants the whole of the specified rectangle.
+ */
+
+typedef struct _rfbFramebufferUpdateRequestMsg {
+ CARD8 type; /* always rfbFramebufferUpdateRequest */
+ CARD8 incremental;
+ CARD16 x;
+ CARD16 y;
+ CARD16 w;
+ CARD16 h;
+} rfbFramebufferUpdateRequestMsg;
+
+#define sz_rfbFramebufferUpdateRequestMsg 10
+
+
+/*-----------------------------------------------------------------------------
+ * KeyEvent - key press or release
+ *
+ * Keys are specified using the "keysym" values defined by the X Window System.
+ * For most ordinary keys, the keysym is the same as the corresponding ASCII
+ * value. Other common keys are:
+ *
+ * BackSpace 0xff08
+ * Tab 0xff09
+ * Return or Enter 0xff0d
+ * Escape 0xff1b
+ * Insert 0xff63
+ * Delete 0xffff
+ * Home 0xff50
+ * End 0xff57
+ * Page Up 0xff55
+ * Page Down 0xff56
+ * Left 0xff51
+ * Up 0xff52
+ * Right 0xff53
+ * Down 0xff54
+ * F1 0xffbe
+ * F2 0xffbf
+ * ... ...
+ * F12 0xffc9
+ * Shift 0xffe1
+ * Control 0xffe3
+ * Meta 0xffe7
+ * Alt 0xffe9
+ */
+
+typedef struct _rfbKeyEventMsg {
+ CARD8 type; /* always rfbKeyEvent */
+ CARD8 down; /* true if down (press), false if up */
+ CARD16 pad;
+ CARD32 key; /* key is specified as an X keysym */
+} rfbKeyEventMsg;
+
+#define sz_rfbKeyEventMsg 8
+
+
+/*-----------------------------------------------------------------------------
+ * PointerEvent - mouse/pen move and/or button press.
+ */
+
+typedef struct _rfbPointerEventMsg {
+ CARD8 type; /* always rfbPointerEvent */
+ CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
+ CARD16 x;
+ CARD16 y;
+} rfbPointerEventMsg;
+
+#define rfbButton1Mask 1
+#define rfbButton2Mask 2
+#define rfbButton3Mask 4
+#define rfbButton4Mask 8
+#define rfbButton5Mask 16
+
+#define sz_rfbPointerEventMsg 6
+
+
+
+/*-----------------------------------------------------------------------------
+ * ClientCutText - the client has new text in its cut buffer.
+ */
+
+typedef struct _rfbClientCutTextMsg {
+ CARD8 type; /* always rfbClientCutText */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 length;
+ /* followed by char text[length] */
+} rfbClientCutTextMsg;
+
+#define sz_rfbClientCutTextMsg 8
+
+/*-----------------------------------------------------------------------------
+ * FileListRequest
+ */
+
+typedef struct _rfbFileListRequestMsg {
+ CARD8 type;
+ CARD8 flags;
+ CARD16 dirNameSize;
+ /* Followed by char Dirname[dirNameSize] */
+} rfbFileListRequestMsg;
+
+#define sz_rfbFileListRequestMsg 4
+
+/*-----------------------------------------------------------------------------
+ * FileDownloadRequest
+ */
+
+typedef struct _rfbFileDownloadRequestMsg {
+ CARD8 type;
+ CARD8 compressedLevel;
+ CARD16 fNameSize;
+ CARD32 position;
+ /* Followed by char Filename[fNameSize] */
+} rfbFileDownloadRequestMsg;
+
+#define sz_rfbFileDownloadRequestMsg 8
+
+/*-----------------------------------------------------------------------------
+ * FileUploadRequest
+ */
+
+typedef struct _rfbFileUploadRequestMsg {
+ CARD8 type;
+ CARD8 compressedLevel;
+ CARD16 fNameSize;
+ CARD32 position;
+ /* Followed by char Filename[fNameSize] */
+} rfbFileUploadRequestMsg;
+
+#define sz_rfbFileUploadRequestMsg 8
+
+
+/*-----------------------------------------------------------------------------
+ * FileUploadData
+ */
+
+typedef struct _rfbFileUploadDataMsg {
+ CARD8 type;
+ CARD8 compressedLevel;
+ CARD16 realSize;
+ CARD16 compressedSize;
+ /* Followed by File[compressedSize] */
+} rfbFileUploadDataMsg;
+
+#define sz_rfbFileUploadDataMsg 8
+
+/*-----------------------------------------------------------------------------
+ * FileDownloadCancel
+ */
+
+typedef struct _rfbFileDownloadCancelMsg {
+ CARD8 type;
+ CARD8 unused;
+ CARD16 reasonLen;
+ /* Followed by reason[reasonLen] */
+} rfbFileDownloadCancelMsg;
+
+#define sz_rfbFileDownloadCancelMsg 4
+
+/*-----------------------------------------------------------------------------
+ * FileUploadFailed
+ */
+
+typedef struct _rfbFileUploadFailedMsg {
+ CARD8 type;
+ CARD8 unused;
+ CARD16 reasonLen;
+ /* Followed by reason[reasonLen] */
+} rfbFileUploadFailedMsg;
+
+#define sz_rfbFileUploadFailedMsg 4
+
+/*-----------------------------------------------------------------------------
+ * FileCreateDirRequest
+ */
+
+typedef struct _rfbFileCreateDirRequestMsg {
+ CARD8 type;
+ CARD8 unused;
+ CARD16 dNameLen;
+ CARD32 dModTime;
+ /* Followed by dName[dNameLen] */
+} rfbFileCreateDirRequestMsg;
+
+#define sz_rfbFileCreateDirRequestMsg 8
+
+/*-----------------------------------------------------------------------------
+ * ChromiumStop - the client has stopped the GL app.
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumStop */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 port;
+} rfbChromiumStopMsg;
+
+#define sz_rfbChromiumStopMsg 8
+
+/*-----------------------------------------------------------------------------
+ * ChromiumExpose - redraw the window
+ */
+
+typedef struct {
+ CARD8 type; /* always rfbChromiumExpose */
+ CARD8 pad1;
+ CARD16 pad2;
+ CARD32 winid;
+} rfbChromiumExposeMsg;
+
+#define sz_rfbChromiumExposeMsg 8
+
+/*-----------------------------------------------------------------------------
+ * Union of all client->server messages.
+ */
+
+typedef union _rfbClientToServerMsg {
+ CARD8 type;
+ rfbSetPixelFormatMsg spf;
+ rfbFixColourMapEntriesMsg fcme;
+ rfbSetEncodingsMsg se;
+ rfbFramebufferUpdateRequestMsg fur;
+ rfbKeyEventMsg ke;
+ rfbPointerEventMsg pe;
+ rfbClientCutTextMsg cct;
+ rfbFileListRequestMsg flr;
+ rfbFileDownloadRequestMsg fdr;
+ rfbFileUploadRequestMsg fupr;
+ rfbFileUploadDataMsg fud;
+ rfbFileDownloadCancelMsg fdc;
+ rfbFileUploadFailedMsg fuf;
+ rfbFileCreateDirRequestMsg fcdr;
+ rfbChromiumStopMsg csd;
+ rfbChromiumExposeMsg cse;
+} rfbClientToServerMsg;
--- xorg-server-1.7.4/hw/vnc/rfbserver.c
+++ xorg-server-1.7.4/hw/vnc/rfbserver.c
@@ -0,0 +1,2308 @@
+/*
+ * rfbserver.c - deal with server-side of the RFB protocol.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2000-2004 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/* Use ``#define CORBA'' to enable CORBA control interface */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "input.h"
+#include "mipointer.h"
+#if XFREE86VNC
+#include <micmap.h>
+#endif
+#ifdef CHROMIUM
+#include "mivalidate.h"
+#endif
+#include "rfb.h"
+#include "windowstr.h"
+#include "sprite.h"
+#include "propertyst.h"
+#include <X11/Xatom.h>
+#include <mi.h>
+
+#ifdef CORBA
+#include <vncserverctrl.h>
+#endif
+
+#ifdef CHROMIUM
+struct CRWindowTable *windowTable = NULL;
+#endif
+
+extern Atom VNC_CONNECT;
+
+rfbClientPtr rfbClientHead = NULL; /* list of all VNC clients/viewers */
+rfbClientPtr pointerClient = NULL; /* Mutex for pointer events */
+
+static rfbClientPtr rfbNewClient(ScreenPtr pScreen, int sock);
+static void rfbProcessClientProtocolVersion(rfbClientPtr cl);
+static void rfbProcessClientInitMessage(rfbClientPtr cl);
+static void rfbSendInteractionCaps(rfbClientPtr cl);
+static void rfbProcessClientNormalMessage(rfbClientPtr cl);
+static Bool rfbSendCopyRegion(rfbClientPtr cl, RegionPtr reg, int dx, int dy);
+static Bool rfbSendLastRectMarker(rfbClientPtr cl);
+
+static char *text = NULL;
+
+void
+rfbRootPropertyChange(ScreenPtr pScreen)
+{
+ PropertyPtr pProp;
+ WindowPtr pWin = WindowTable[pScreen->myNum];
+
+ pProp = wUserProps (pWin);
+
+ while (pProp) {
+ if ((pProp->propertyName == XA_CUT_BUFFER0) &&
+ (pProp->type == XA_STRING) &&
+ (pProp->format == 8))
+ {
+ /* Ensure we don't keep re-sending cut buffer */
+
+ if ( (text && pProp->data && strncmp(text, pProp->data, pProp->size)) || !text)
+ rfbGotXCutText(pProp->data, pProp->size);
+
+ if (text) xfree(text);
+ text = xalloc(1 + pProp->size);
+ if (! text) return;
+ if (pProp->data) memcpy(text, pProp->data, pProp->size);
+ text[pProp->size] = '\0';
+
+ return;
+ }
+ if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING)
+ && (pProp->format == 8) && (pProp->size > 0))
+ {
+ int i;
+ rfbClientPtr cl;
+ int port = 5500;
+ char *host = (char *)Xalloc(pProp->size+1);
+ memcpy(host, pProp->data, pProp->size);
+ host[pProp->size] = 0;
+ for (i = 0; i < pProp->size; i++) {
+ if (host[i] == ':') {
+ port = atoi(&host[i+1]);
+ host[i] = 0;
+ }
+ }
+
+ cl = rfbReverseConnection(pScreen, host, port);
+
+#ifdef CORBA
+ if (cl != NULL)
+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1);
+#endif
+
+ ChangeWindowProperty(pWin,
+ pProp->propertyName, pProp->type,
+ pProp->format, PropModeReplace,
+ 0, NULL,
+ FALSE
+ );
+
+ free(host);
+ }
+ pProp = pProp->next;
+ }
+}
+
+int
+rfbBitsPerPixel(depth)
+ int depth;
+{
+ if (depth == 1) return 1;
+ else if (depth <= 8) return 8;
+ else if (depth <= 16) return 16;
+ else return 32;
+}
+
+void
+rfbUserAllow(int sock, int accept)
+{
+ rfbClientPtr cl;
+
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ if (cl->sock == sock) {
+ cl->userAccepted = accept;
+ }
+ }
+}
+
+/*
+ * rfbNewClientConnection is called from sockets.c when a new connection
+ * comes in.
+ */
+
+void
+rfbNewClientConnection(ScreenPtr pScreen, int sock)
+{
+ rfbClientPtr cl;
+
+ cl = rfbNewClient(pScreen, sock);
+
+ GenerateVncConnectedEvent(sock);
+
+#if XFREE86VNC
+ /* Someone is connected - disable VT switching */
+ xf86EnableVTSwitch(FALSE);
+#endif
+
+#ifdef CORBA
+ if (cl != NULL)
+ newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE), 1, 1, 1);
+#endif
+}
+
+
+/*
+ * rfbReverseConnection is called by the CORBA stuff to make an outward
+ * connection to a "listening" RFB client.
+ */
+
+rfbClientPtr
+rfbReverseConnection(ScreenPtr pScreen, char *host, int port)
+{
+ int sock;
+ rfbClientPtr cl;
+
+ if ((sock = rfbConnect(pScreen, host, port)) < 0)
+ return (rfbClientPtr)NULL;
+
+ cl = rfbNewClient(pScreen, sock);
+
+ if (cl) {
+ cl->reverseConnection = TRUE;
+ }
+
+ return cl;
+}
+
+
+#ifdef CHROMIUM
+/*
+ * rfbSetClip --
+ * Generate expose event.
+ * This function is overkill and should be cleaned up, but it
+ * works for now.
+ */
+
+void
+rfbSetClip (WindowPtr pWin, BOOL enable)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ 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 = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_SUBTRACT(pScreen, 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;
+ REGION_INIT (pScreen, &pWin->winSize, &box, 1);
+ REGION_INIT (pScreen, &pWin->borderSize, &box, 1);
+ if (WasViewable)
+ REGION_RESET(pScreen, &pWin->borderClip, &box);
+ pWin->drawable.width = pScreen->width;
+ pWin->drawable.height = pScreen->height;
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+ else
+ {
+ REGION_EMPTY(pScreen, &pWin->borderClip);
+ REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList);
+ }
+
+ ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
+
+ if (WasViewable)
+ {
+ if (pWin->backStorage)
+ {
+ pOldClip = REGION_CREATE(pScreen, NullBox, 1);
+ REGION_COPY(pScreen, 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 &&
+ ((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)
+ REGION_DESTROY(pScreen, pOldClip);
+ if (bsExposed)
+ {
+ RegionPtr valExposed = NullRegion;
+
+ if (pWin->valdata)
+ valExposed = &pWin->valdata->after.exposed;
+ (*pScreen->WindowExposures) (pWin, valExposed, bsExposed);
+ if (valExposed)
+ REGION_EMPTY(pScreen, valExposed);
+ REGION_DESTROY(pScreen, 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 ();
+}
+#endif /* CHROMIUM */
+
+/*
+ * rfbNewClient is called when a new connection has been made by whatever
+ * means.
+ */
+
+static rfbClientPtr
+rfbNewClient(ScreenPtr pScreen, int sock)
+{
+ rfbProtocolVersionMsg pv;
+ rfbClientPtr cl;
+ BoxRec box;
+ struct sockaddr_in addr;
+ SOCKLEN_T addrlen = sizeof(struct sockaddr_in);
+ VNCSCREENPTR(pScreen);
+ int i;
+
+ if (rfbClientHead == NULL) {
+ /* no other clients - make sure we don't think any keys are pressed */
+ KbdReleaseAllKeys();
+ } else {
+ rfbLog(" (other clients");
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ rfbLog(" %s",cl->host);
+ }
+ rfbLog(")\n");
+ }
+
+ cl = (rfbClientPtr)xalloc(sizeof(rfbClientRec));
+
+#ifdef CHROMIUM
+ cl->chromium_port = 0; /* no GL application on this port, yet */
+#endif
+ cl->userAccepted = 0; /* user hasn't even approached this yet .... */
+ cl->sock = sock;
+ getpeername(sock, (struct sockaddr *)&addr, &addrlen);
+ cl->host = strdup(inet_ntoa(addr.sin_addr));
+ cl->login = NULL;
+
+ /* Dispatch client input to rfbProcessClientProtocolVersion(). */
+ cl->state = RFB_PROTOCOL_VERSION;
+
+ cl->viewOnly = FALSE;
+ cl->reverseConnection = FALSE;
+ cl->readyForSetColourMapEntries = FALSE;
+ cl->useCopyRect = FALSE;
+ cl->preferredEncoding = rfbEncodingRaw;
+ cl->correMaxWidth = 48;
+ cl->correMaxHeight = 48;
+ cl->pScreen = pScreen;
+
+ REGION_NULL(pScreen,&cl->copyRegion);
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+
+ box.x1 = box.y1 = 0;
+ box.x2 = pVNC->width;
+ box.y2 = pVNC->height;
+ REGION_INIT(pScreen,&cl->modifiedRegion,&box,0);
+
+ REGION_NULL(pScreen,&cl->requestedRegion);
+
+ cl->deferredUpdateScheduled = FALSE;
+ cl->deferredUpdateTimer = NULL;
+
+ cl->format = pVNC->rfbServerFormat;
+ cl->translateFn = rfbTranslateNone;
+ cl->translateLookupTable = NULL;
+
+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
+ cl->tightQualityLevel = -1;
+ for (i = 0; i < 4; i++)
+ cl->zsActive[i] = FALSE;
+
+ cl->enableCursorShapeUpdates = FALSE;
+ cl->enableCursorPosUpdates = FALSE;
+ cl->enableLastRectEncoding = FALSE;
+#ifdef CHROMIUM
+ cl->enableChromiumEncoding = FALSE;
+#endif
+
+ cl->next = rfbClientHead;
+ rfbClientHead = cl;
+
+ rfbResetStats(cl);
+
+ cl->compStreamInited = FALSE;
+ cl->compStream.total_in = 0;
+ cl->compStream.total_out = 0;
+ cl->compStream.zalloc = Z_NULL;
+ cl->compStream.zfree = Z_NULL;
+ cl->compStream.opaque = Z_NULL;
+
+ cl->zlibCompressLevel = 5;
+
+ sprintf(pv,rfbProtocolVersionFormat,rfbProtocolMajorVersion,
+ rfbProtocolMinorVersion);
+
+ if (WriteExact(sock, pv, sz_rfbProtocolVersionMsg) < 0) {
+ rfbLogPerror("rfbNewClient: write");
+ rfbCloseSock(pScreen, sock);
+ return NULL;
+ }
+
+ return cl;
+}
+
+
+/*
+ * rfbClientConnectionGone is called from sockets.c just after a connection
+ * has gone away.
+ */
+
+void
+rfbClientConnectionGone(sock)
+ int sock;
+{
+ rfbClientPtr cl, prev;
+ int i;
+#if XFREE86VNC
+ int allowvt = TRUE;
+#endif
+
+ for (prev = NULL, cl = rfbClientHead; cl; prev = cl, cl = cl->next) {
+ if (sock == cl->sock)
+ break;
+ }
+
+ if (!cl) {
+ rfbLog("rfbClientConnectionGone: unknown socket %d\n",sock);
+ return;
+ }
+
+ rfbLog("rfbClientConnectionGone\n");
+
+ if (cl->login != NULL) {
+ rfbLog("VNC Client %s (%s) gone\n", cl->login, cl->host);
+ free(cl->login);
+ } else {
+ rfbLog("VNC Client %s gone\n", cl->host);
+ }
+ free(cl->host);
+
+ /* Release the compression state structures if any. */
+ if ( cl->compStreamInited == TRUE ) {
+ deflateEnd( &(cl->compStream) );
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (cl->zsActive[i])
+ deflateEnd(&cl->zsStruct[i]);
+ }
+
+ if (pointerClient == cl)
+ pointerClient = NULL;
+
+#ifdef CORBA
+ destroyConnection(cl);
+#endif
+
+ if (prev)
+ prev->next = cl->next;
+ else
+ rfbClientHead = cl->next;
+
+ REGION_UNINIT(cl->pScreen,&cl->copyRegion);
+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion);
+ TimerFree(cl->deferredUpdateTimer);
+
+ rfbPrintStats(cl);
+
+ if (cl->translateLookupTable) free(cl->translateLookupTable);
+
+ xfree(cl);
+
+ GenerateVncDisconnectedEvent(sock);
+
+#if XFREE86VNC
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ /* still someone connected */
+ allowvt = FALSE;
+ }
+
+ xf86EnableVTSwitch(allowvt);
+#endif
+}
+
+
+/*
+ * rfbProcessClientMessage is called when there is data to read from a client.
+ */
+
+void
+rfbProcessClientMessage(ScreenPtr pScreen, int sock)
+{
+ rfbClientPtr cl;
+
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+ if (sock == cl->sock)
+ break;
+ }
+
+ if (!cl) {
+ rfbLog("rfbProcessClientMessage: unknown socket %d\n",sock);
+ rfbCloseSock(pScreen, sock);
+ return;
+ }
+
+#ifdef CORBA
+ if (isClosePending(cl)) {
+ rfbLog("Closing connection to client %s\n", cl->host);
+ rfbCloseSock(pScreen, sock);
+ return;
+ }
+#endif
+
+ switch (cl->state) {
+ case RFB_PROTOCOL_VERSION:
+ rfbProcessClientProtocolVersion(cl);
+ break;
+ case RFB_SECURITY_TYPE: /* protocol 3.7 */
+ rfbProcessClientSecurityType(cl);
+ break;
+ case RFB_TUNNELING_TYPE: /* protocol 3.7t */
+ rfbProcessClientTunnelingType(cl);
+ break;
+ case RFB_AUTH_TYPE: /* protocol 3.7t */
+ rfbProcessClientAuthType(cl);
+ break;
+ case RFB_AUTHENTICATION:
+ rfbVncAuthProcessResponse(cl);
+ break;
+ case RFB_INITIALISATION:
+ rfbProcessClientInitMessage(cl);
+ break;
+ default:
+ rfbProcessClientNormalMessage(cl);
+ }
+}
+
+
+/*
+ * rfbProcessClientProtocolVersion is called when the client sends its
+ * protocol version.
+ */
+
+static void
+rfbProcessClientProtocolVersion(cl)
+ rfbClientPtr cl;
+{
+ rfbProtocolVersionMsg pv;
+ int n, major, minor;
+
+ if ((n = ReadExact(cl->sock, pv, sz_rfbProtocolVersionMsg)) <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientProtocolVersion: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientProtocolVersion: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ pv[sz_rfbProtocolVersionMsg] = 0;
+ if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {
+ rfbLog("rfbProcessClientProtocolVersion: not a valid RFB client\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ rfbLog("Using protocol version %d.%d\n", major, minor);
+
+ if (major != rfbProtocolMajorVersion) {
+ rfbLog("RFB protocol version mismatch - server %d.%d, client %d.%d\n",
+ rfbProtocolMajorVersion,rfbProtocolMinorVersion,major,minor);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Always use one of the two standard versions of the RFB protocol. */
+ cl->protocol_minor_ver = minor;
+ if (minor > rfbProtocolMinorVersion) {
+ cl->protocol_minor_ver = rfbProtocolMinorVersion;
+ } else if (minor < rfbProtocolMinorVersion) {
+ cl->protocol_minor_ver = rfbProtocolFallbackMinorVersion;
+ }
+ if (minor != rfbProtocolMinorVersion &&
+ minor != rfbProtocolFallbackMinorVersion) {
+ rfbLog("Non-standard protocol version %d.%d, using %d.%d instead\n",
+ major, minor, rfbProtocolMajorVersion, cl->protocol_minor_ver);
+ }
+
+ /* TightVNC protocol extensions are not enabled yet. */
+ cl->protocol_tightvnc = FALSE;
+
+ rfbAuthNewClient(cl);
+}
+
+/*
+ * rfbClientConnFailed is called when a client connection has failed
+ * before the authentication stage.
+ */
+
+void
+rfbClientConnFailed(cl, reason)
+ rfbClientPtr cl;
+ char *reason;
+{
+ int headerLen, reasonLen;
+ char buf[8];
+
+ headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4;
+ reasonLen = strlen(reason);
+ ((CARD32 *)buf)[0] = 0;
+ ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen);
+
+ if ( WriteExact(cl->sock, buf, headerLen) < 0 ||
+ WriteExact(cl->sock, buf + 4, 4) < 0 ||
+ WriteExact(cl->sock, reason, reasonLen) < 0 ) {
+ rfbLogPerror("rfbClientConnFailed: write");
+ }
+
+ rfbCloseSock(cl->pScreen, cl->sock);
+}
+
+
+/*
+ * rfbProcessClientInitMessage is called when the client sends its
+ * initialisation message.
+ */
+
+static void
+rfbProcessClientInitMessage(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbClientInitMsg ci;
+ char buf[256];
+ rfbServerInitMsg *si = (rfbServerInitMsg *)buf;
+ struct passwd *user;
+ int len, n;
+ rfbClientPtr otherCl, nextCl;
+
+ if ((n = ReadExact(cl->sock, (char *)&ci,sz_rfbClientInitMsg)) <= 0) {
+ if (n == 0)
+ rfbLog("rfbProcessClientInitMessage: client gone\n");
+ else
+ rfbLogPerror("rfbProcessClientInitMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ si->framebufferWidth = Swap16IfLE(pVNC->width);
+ si->framebufferHeight = Swap16IfLE(pVNC->height);
+ si->format = pVNC->rfbServerFormat;
+ si->format.redMax = Swap16IfLE(si->format.redMax);
+ si->format.greenMax = Swap16IfLE(si->format.greenMax);
+ si->format.blueMax = Swap16IfLE(si->format.blueMax);
+
+ user = getpwuid(getuid());
+
+ if (strlen(desktopName) > 128) /* sanity check on desktop name len */
+ desktopName[128] = 0;
+
+ if (user) {
+ sprintf(buf + sz_rfbServerInitMsg, "%s's %s desktop (%s:%s)",
+ user->pw_name, desktopName, rfbThisHost, display);
+ } else {
+ sprintf(buf + sz_rfbServerInitMsg, "%s desktop (%s:%s)",
+ desktopName, rfbThisHost, display);
+ }
+ len = strlen(buf + sz_rfbServerInitMsg);
+ si->nameLength = Swap32IfLE(len);
+
+ if (WriteExact(cl->sock, buf, sz_rfbServerInitMsg + len) < 0) {
+ rfbLogPerror("rfbProcessClientInitMessage: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ if (cl->protocol_tightvnc)
+ rfbSendInteractionCaps(cl); /* protocol 3.7t */
+
+ /* Dispatch client input to rfbProcessClientNormalMessage(). */
+ cl->state = RFB_NORMAL;
+
+ if (!cl->reverseConnection &&
+ (pVNC->rfbNeverShared || (!pVNC->rfbAlwaysShared && !ci.shared))) {
+
+ if (pVNC->rfbDontDisconnect) {
+ for (otherCl = rfbClientHead; otherCl; otherCl = otherCl->next) {
+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
+ rfbLog("-dontdisconnect: Not shared & existing client\n");
+ rfbLog(" refusing new client %s\n", cl->host);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ }
+ } else {
+ for (otherCl = rfbClientHead; otherCl; otherCl = nextCl) {
+ nextCl = otherCl->next;
+ if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) {
+ rfbLog("Not shared - closing connection to client %s\n",
+ otherCl->host);
+ rfbCloseSock(otherCl->pScreen, otherCl->sock);
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * rfbSendInteractionCaps is called after sending the server
+ * initialisation message, only if the protocol version is 3.130.
+ * In this function, we send the lists of supported protocol messages
+ * and encodings.
+ */
+
+/* Update these constants on changing capability lists below! */
+#define N_SMSG_CAPS 0
+#define N_CMSG_CAPS 0
+#define N_ENC_CAPS 12
+
+void
+rfbSendInteractionCaps(cl)
+ rfbClientPtr cl;
+{
+ rfbInteractionCapsMsg intr_caps;
+ rfbCapabilityInfo enc_list[N_ENC_CAPS];
+ int i;
+
+ /* Fill in the header structure sent prior to capability lists. */
+ intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS);
+ intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS);
+ intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS);
+ intr_caps.pad = 0;
+
+ /* Supported server->client message types. */
+ /* For future file transfer support:
+ i = 0;
+ SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor);
+ SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor);
+ SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor);
+ SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor);
+ if (i != N_SMSG_CAPS) {
+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ */
+
+ /* Supported client->server message types. */
+ /* For future file transfer support:
+ i = 0;
+ SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor);
+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor);
+ SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor);
+ SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor);
+ SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor);
+ SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor);
+ if (i != N_CMSG_CAPS) {
+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ */
+
+ /* Encoding types. */
+ i = 0;
+ SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor);
+ SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor);
+ if (i != N_ENC_CAPS) {
+ rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Send header and capability lists */
+ if (WriteExact(cl->sock, (char *)&intr_caps,
+ sz_rfbInteractionCapsMsg) < 0 ||
+ WriteExact(cl->sock, (char *)&enc_list[0],
+ sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) {
+ rfbLogPerror("rfbSendInteractionCaps: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* Dispatch client input to rfbProcessClientNormalMessage(). */
+ cl->state = RFB_NORMAL;
+}
+
+
+/*
+ * rfbProcessClientNormalMessage is called when the client has sent a normal
+ * protocol message.
+ */
+
+static void
+rfbProcessClientNormalMessage(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int n;
+ rfbClientToServerMsg msg;
+ char *str;
+
+ if (pVNC->rfbUserAccept) {
+ /*
+ * We've asked for another level of user authentication
+ * If the user has not validated this connected, don't
+ * process it.
+ */
+ /*
+ * NOTE: we do it here, so the vncviewer knows it's
+ * connected, but waiting for the first screen update
+ */
+ if (cl->userAccepted == VNC_USER_UNDEFINED) {
+ usleep(10);
+ return;
+ }
+ if (cl->userAccepted == VNC_USER_DISCONNECT) {
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ }
+
+ if ((n = ReadExact(cl->sock, (char *)&msg, 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ switch (msg.type) {
+
+ case rfbSetPixelFormat:
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbSetPixelFormatMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel;
+ cl->format.depth = msg.spf.format.depth;
+ cl->format.bigEndian = (msg.spf.format.bigEndian ? 1 : 0);
+ cl->format.trueColour = (msg.spf.format.trueColour ? 1 : 0);
+ cl->format.redMax = Swap16IfLE(msg.spf.format.redMax);
+ cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax);
+ cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax);
+ cl->format.redShift = msg.spf.format.redShift;
+ cl->format.greenShift = msg.spf.format.greenShift;
+ cl->format.blueShift = msg.spf.format.blueShift;
+
+ cl->readyForSetColourMapEntries = TRUE;
+
+ rfbSetTranslateFunction(cl);
+ return;
+
+
+ case rfbFixColourMapEntries:
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbFixColourMapEntriesMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ rfbLog("rfbProcessClientNormalMessage: %s",
+ "FixColourMapEntries unsupported\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+
+
+ case rfbSetEncodings:
+ {
+ int i;
+ CARD32 enc;
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbSetEncodingsMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings);
+
+ cl->preferredEncoding = -1;
+ cl->useCopyRect = FALSE;
+ cl->enableCursorShapeUpdates = FALSE;
+ cl->enableCursorPosUpdates = FALSE;
+ cl->enableLastRectEncoding = FALSE;
+#ifdef CHROMIUM
+ cl->enableChromiumEncoding = FALSE;
+#endif
+ cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION;
+ cl->tightQualityLevel = -1;
+
+ for (i = 0; i < msg.se.nEncodings; i++) {
+ if ((n = ReadExact(cl->sock, (char *)&enc, 4)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+ enc = Swap32IfLE(enc);
+
+ switch (enc) {
+
+ case rfbEncodingCopyRect:
+ cl->useCopyRect = TRUE;
+ rfbLog("Using copyrect encoding for client %s\n",
+ cl->host);
+ break;
+ case rfbEncodingRaw:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using raw encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingRRE:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using rre encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingCoRRE:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using CoRRE encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingHextile:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using hextile encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingZlib:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using zlib encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingTight:
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = enc;
+ rfbLog("Using tight encoding for client %s\n",
+ cl->host);
+ }
+ break;
+ case rfbEncodingXCursor:
+ rfbLog("Enabling X-style cursor updates for client %s\n",
+ cl->host);
+ cl->enableCursorShapeUpdates = TRUE;
+ cl->useRichCursorEncoding = FALSE;
+ cl->cursorWasChanged = TRUE;
+ break;
+ case rfbEncodingRichCursor:
+ if (!cl->enableCursorShapeUpdates) {
+ rfbLog("Enabling full-color cursor updates for client "
+ "%s\n", cl->host);
+ cl->enableCursorShapeUpdates = TRUE;
+ cl->useRichCursorEncoding = TRUE;
+ cl->cursorWasChanged = TRUE;
+ }
+ break;
+ case rfbEncodingPointerPos:
+ if (!cl->enableCursorPosUpdates) {
+ rfbLog("Enabling cursor position updates for client %s\n",
+ cl->host);
+ cl->enableCursorPosUpdates = TRUE;
+ cl->cursorWasMoved = TRUE;
+ cl->cursorX = -1;
+ cl->cursorY = -1;
+ }
+ break;
+ case rfbEncodingLastRect:
+ if (!cl->enableLastRectEncoding) {
+ rfbLog("Enabling LastRect protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableLastRectEncoding = TRUE;
+ }
+ break;
+#ifdef CHROMIUM
+ case rfbEncodingChromium:
+ case rfbEncodingChromium2:
+ if (!cl->enableChromiumEncoding) {
+ cl->enableChromiumEncoding = TRUE;
+ /* This tells OpenGL apps/replicate SPUs that new viewer
+ * has attached.
+ */
+ GenerateVncChromiumConnectedEvent(cl->sock);
+ if (enc == rfbEncodingChromium) {
+ /* Generate exposures for all windows */
+ WindowPtr pWin = WindowTable[cl->pScreen->myNum];
+ rfbSetClip(pWin, 1);
+ }
+ else {
+ /* don't generate exposures for Chromium2 because
+ * that confused DMX.
+ */
+ }
+ }
+ break;
+#endif
+ default:
+ if ( enc >= (CARD32)rfbEncodingCompressLevel0 &&
+ enc <= (CARD32)rfbEncodingCompressLevel9 ) {
+ cl->zlibCompressLevel = enc & 0x0F;
+ cl->tightCompressLevel = enc & 0x0F;
+ rfbLog("Using compression level %d for client %s\n",
+ cl->tightCompressLevel, cl->host);
+ } else if ( enc >= (CARD32)rfbEncodingQualityLevel0 &&
+ enc <= (CARD32)rfbEncodingQualityLevel9 ) {
+ cl->tightQualityLevel = enc & 0x0F;
+ rfbLog("Using image quality level %d for client %s\n",
+ cl->tightQualityLevel, cl->host);
+ } else {
+ rfbLog("rfbProcessClientNormalMessage: ignoring unknown "
+ "encoding %d\n", (int)enc);
+ }
+ }
+ }
+
+ if (cl->preferredEncoding == -1) {
+ cl->preferredEncoding = rfbEncodingRaw;
+ rfbLog("No encoding specified - using raw encoding for client %s\n",
+ cl->host);
+ }
+
+ if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) {
+ rfbLog("Disabling cursor position updates for client %s\n",
+ cl->host);
+ cl->enableCursorPosUpdates = FALSE;
+ }
+
+#if XFREE86VNC
+ /*
+ * With XFree86 and the hardware cursor's we need to put up the
+ * cursor again, and if we've detected a cursor shapeless client
+ * we need to disable hardware cursors.
+ */
+ if (!cl->enableCursorShapeUpdates)
+ pVNC->SWCursor = (Bool *)TRUE;
+ else
+ pVNC->SWCursor = (Bool *)FALSE;
+
+ {
+ int x, y;
+ miPointerPosition(&x, &y); /*XXX deprecated*/
+ (*pVNC->spriteFuncs->SetCursor)(cl->pScreen, pVNC->pCurs, x, y);
+ }
+#endif
+
+ return;
+ }
+
+
+ case rfbFramebufferUpdateRequest:
+ {
+ RegionRec tmpRegion;
+ BoxRec box;
+
+#ifdef CORBA
+ addCapability(cl, DISPLAY_DEVICE);
+#endif
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ box.x1 = Swap16IfLE(msg.fur.x);
+ box.y1 = Swap16IfLE(msg.fur.y);
+ box.x2 = box.x1 + Swap16IfLE(msg.fur.w);
+ box.y2 = box.y1 + Swap16IfLE(msg.fur.h);
+ SAFE_REGION_INIT(cl->pScreen,&tmpRegion,&box,0);
+
+ REGION_UNION(cl->pScreen, &cl->requestedRegion, &cl->requestedRegion,
+ &tmpRegion);
+
+ if (!cl->readyForSetColourMapEntries) {
+ /* client hasn't sent a SetPixelFormat so is using server's */
+ cl->readyForSetColourMapEntries = TRUE;
+ if (!cl->format.trueColour) {
+ if (!rfbSetClientColourMap(cl, 0, 0)) {
+ REGION_UNINIT(cl->pScreen,&tmpRegion);
+ return;
+ }
+ }
+ }
+
+ if (!msg.fur.incremental) {
+ REGION_UNION(cl->pScreen,&cl->modifiedRegion,&cl->modifiedRegion,
+ &tmpRegion);
+ REGION_SUBTRACT(cl->pScreen,&cl->copyRegion,&cl->copyRegion,
+ &tmpRegion);
+ }
+
+#ifndef DMXVNC
+ /* don't try to send any pixel data - we'll crash */
+ if (FB_UPDATE_PENDING(cl)) {
+ rfbSendFramebufferUpdate(cl->pScreen, cl);
+ }
+#endif
+
+ REGION_UNINIT(cl->pScreen,&tmpRegion);
+ return;
+ }
+
+ case rfbKeyEvent:
+
+ cl->rfbKeyEventsRcvd++;
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbKeyEventMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+#ifdef CORBA
+ addCapability(cl, KEYBOARD_DEVICE);
+
+ if (!isKeyboardEnabled(cl))
+ return;
+#endif
+ /*ErrorF("Key event: %d\n", msg.ke.key);*/
+ if (!pVNC->rfbViewOnly && !cl->viewOnly) {
+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
+ }
+ return;
+
+
+ case rfbPointerEvent:
+
+ cl->rfbPointerEventsRcvd++;
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbPointerEventMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+#ifdef CORBA
+ addCapability(cl, POINTER_DEVICE);
+
+ if (!isPointerEnabled(cl))
+ return;
+#endif
+
+ if (pointerClient && (pointerClient != cl))
+ return;
+
+ if (msg.pe.buttonMask == 0)
+ pointerClient = NULL;
+ else
+ pointerClient = cl;
+
+ if (!pVNC->rfbViewOnly && !cl->viewOnly) {
+ cl->cursorX = (int)Swap16IfLE(msg.pe.x);
+ cl->cursorY = (int)Swap16IfLE(msg.pe.y);
+ PtrAddEvent(msg.pe.buttonMask, cl->cursorX, cl->cursorY, cl);
+ }
+ return;
+
+
+ case rfbClientCutText:
+
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbClientCutTextMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ msg.cct.length = Swap32IfLE(msg.cct.length);
+
+ str = (char *)xalloc(msg.cct.length);
+
+ if ((n = ReadExact(cl->sock, str, msg.cct.length)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ xfree(str);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* NOTE: We do not accept cut text from a view-only client */
+ if (!cl->viewOnly)
+ rfbSetXCutText(str, msg.cct.length);
+
+ xfree(str);
+ return;
+
+#ifdef CHROMIUM
+ case rfbChromiumStop:
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbChromiumStopMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* would we use msg.csd.port ??? */
+
+ cl->chromium_port = 0;
+
+ /* tear down window information */
+ {
+ CRWindowTable *wt, *nextWt = NULL;
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ xfree(wt);
+ }
+
+ windowTable = NULL;
+ }
+
+ return;
+
+ case rfbChromiumExpose:
+ if ((n = ReadExact(cl->sock, ((char *)&msg) + 1,
+ sz_rfbChromiumExposeMsg - 1)) <= 0) {
+ if (n != 0)
+ rfbLogPerror("rfbProcessClientNormalMessage: read");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+
+ /* find the window and re-expose it */
+ {
+ CRWindowTable *wt, *nextWt = NULL;
+
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->CRwinId == msg.cse.winid) {
+ WindowPtr pWin;
+ pWin = LookupIDByType(wt->XwinId, RT_WINDOW);
+ if (pWin) {
+ miSendExposures(pWin, &pWin->clipList,
+ pWin->drawable.x,
+ pWin->drawable.y);
+ FlushAllOutput();
+ }
+ }
+ }
+ }
+
+ return;
+#endif
+
+ default:
+
+ rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n",
+ msg.type);
+ rfbLog(" ... closing connection\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return;
+ }
+}
+
+
+
+/*
+ * rfbSendFramebufferUpdate - send the currently pending framebuffer update to
+ * the RFB client.
+ */
+
+Bool
+rfbSendFramebufferUpdate(pScreen, cl)
+ ScreenPtr pScreen;
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(pScreen);
+ int i;
+ int nUpdateRegionRects;
+ rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)pVNC->updateBuf;
+ RegionRec updateRegion, updateCopyRegion;
+ int dx, dy;
+ Bool sendCursorShape = FALSE;
+ Bool sendCursorPos = FALSE;
+
+ /*
+ * If this client understands cursor shape updates, cursor should be
+ * removed from the framebuffer. Otherwise, make sure it's put up.
+ */
+
+#if !XFREE86VNC
+ if (cl->enableCursorShapeUpdates) {
+ if (pVNC->cursorIsDrawn)
+ rfbSpriteRemoveCursor(pScreen);
+ if (!pVNC->cursorIsDrawn && cl->cursorWasChanged)
+ sendCursorShape = TRUE;
+ } else {
+ if (!pVNC->cursorIsDrawn)
+ rfbSpriteRestoreCursor(pScreen);
+ }
+#else
+ if (cl->enableCursorShapeUpdates)
+ if (cl->cursorWasChanged)
+ sendCursorShape = TRUE;
+#endif
+
+ /*
+ * Do we plan to send cursor position update?
+ */
+
+ if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
+ sendCursorPos = TRUE;
+
+ /*
+ * The modifiedRegion may overlap the destination copyRegion. We remove
+ * any overlapping bits from the copyRegion (since they'd only be
+ * overwritten anyway).
+ */
+
+ REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion,
+ &cl->modifiedRegion);
+
+ /*
+ * The client is interested in the region requestedRegion. The region
+ * which should be updated now is the intersection of requestedRegion
+ * and the union of modifiedRegion and copyRegion. If it's empty then
+ * no update is needed.
+ */
+
+ REGION_NULL(pScreen,&updateRegion);
+ REGION_UNION(pScreen, &updateRegion, &cl->copyRegion,
+ &cl->modifiedRegion);
+ REGION_INTERSECT(pScreen, &updateRegion, &cl->requestedRegion,
+ &updateRegion);
+
+ if ( !REGION_NOTEMPTY(pScreen,&updateRegion) &&
+ !sendCursorShape && !sendCursorPos ) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return TRUE;
+ }
+
+ /*
+ * We assume that the client doesn't have any pixel data outside the
+ * requestedRegion. In other words, both the source and destination of a
+ * copy must lie within requestedRegion. So the region we can send as a
+ * copy is the intersection of the copyRegion with both the requestedRegion
+ * and the requestedRegion translated by the amount of the copy. We set
+ * updateCopyRegion to this.
+ */
+
+ REGION_NULL(pScreen,&updateCopyRegion);
+ REGION_INTERSECT(pScreen, &updateCopyRegion, &cl->copyRegion,
+ &cl->requestedRegion);
+ REGION_TRANSLATE(pScreen, &cl->requestedRegion, cl->copyDX, cl->copyDY);
+ REGION_INTERSECT(pScreen, &updateCopyRegion, &updateCopyRegion,
+ &cl->requestedRegion);
+ dx = cl->copyDX;
+ dy = cl->copyDY;
+
+ /*
+ * Next we remove updateCopyRegion from updateRegion so that updateRegion
+ * is the part of this update which is sent as ordinary pixel data (i.e not
+ * a copy).
+ */
+
+ REGION_SUBTRACT(pScreen, &updateRegion, &updateRegion, &updateCopyRegion);
+
+ /*
+ * Finally we leave modifiedRegion to be the remainder (if any) of parts of
+ * the screen which are modified but outside the requestedRegion. We also
+ * empty both the requestedRegion and the copyRegion - note that we never
+ * carry over a copyRegion for a future update.
+ */
+
+ REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &cl->copyRegion);
+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &updateRegion);
+ REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
+ &updateCopyRegion);
+
+ REGION_EMPTY(pScreen, &cl->requestedRegion);
+ REGION_EMPTY(pScreen, &cl->copyRegion);
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+
+ /*
+ * Now send the update.
+ */
+
+ cl->rfbFramebufferUpdateMessagesSent++;
+
+ if (cl->preferredEncoding == rfbEncodingCoRRE) {
+ nUpdateRegionRects = 0;
+
+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) {
+ int x = REGION_RECTS(&updateRegion)[i].x1;
+ int y = REGION_RECTS(&updateRegion)[i].y1;
+ int w = REGION_RECTS(&updateRegion)[i].x2 - x;
+ int h = REGION_RECTS(&updateRegion)[i].y2 - y;
+ nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1)
+ * ((h-1) / cl->correMaxHeight + 1));
+ }
+ } else if (cl->preferredEncoding == rfbEncodingZlib) {
+ nUpdateRegionRects = 0;
+
+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) {
+ int x = REGION_RECTS(&updateRegion)[i].x1;
+ int y = REGION_RECTS(&updateRegion)[i].y1;
+ int w = REGION_RECTS(&updateRegion)[i].x2 - x;
+ int h = REGION_RECTS(&updateRegion)[i].y2 - y;
+ nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1);
+ }
+ } else if (cl->preferredEncoding == rfbEncodingTight) {
+ nUpdateRegionRects = 0;
+
+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) {
+ int x = REGION_RECTS(&updateRegion)[i].x1;
+ int y = REGION_RECTS(&updateRegion)[i].y1;
+ int w = REGION_RECTS(&updateRegion)[i].x2 - x;
+ int h = REGION_RECTS(&updateRegion)[i].y2 - y;
+ int n = rfbNumCodedRectsTight(cl, x, y, w, h);
+ if (n == 0) {
+ nUpdateRegionRects = 0xFFFF;
+ break;
+ }
+ nUpdateRegionRects += n;
+ }
+ } else {
+ nUpdateRegionRects = REGION_NUM_RECTS(&updateRegion);
+ }
+
+ fu->type = rfbFramebufferUpdate;
+ if (nUpdateRegionRects != 0xFFFF) {
+ fu->nRects = Swap16IfLE(REGION_NUM_RECTS(&updateCopyRegion) +
+ nUpdateRegionRects +
+ !!sendCursorShape + !!sendCursorPos);
+ } else {
+ fu->nRects = 0xFFFF;
+ }
+ pVNC->ublen = sz_rfbFramebufferUpdateMsg;
+
+ if (sendCursorShape) {
+ cl->cursorWasChanged = FALSE;
+ if (!rfbSendCursorShape(cl, pScreen))
+ return FALSE;
+ }
+
+ if (sendCursorPos) {
+ cl->cursorWasMoved = FALSE;
+ if (!rfbSendCursorPos(cl, pScreen))
+ return FALSE;
+ }
+
+ if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) {
+ if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ REGION_UNINIT(pScreen,&updateCopyRegion);
+ return FALSE;
+ }
+ }
+
+ REGION_UNINIT(pScreen,&updateCopyRegion);
+
+ for (i = 0; i < REGION_NUM_RECTS(&updateRegion); i++) {
+ int x = REGION_RECTS(&updateRegion)[i].x1;
+ int y = REGION_RECTS(&updateRegion)[i].y1;
+ int w = REGION_RECTS(&updateRegion)[i].x2 - x;
+ int h = REGION_RECTS(&updateRegion)[i].y2 - y;
+
+ cl->rfbRawBytesEquivalent += (sz_rfbFramebufferUpdateRectHeader
+ + w * (cl->format.bitsPerPixel / 8) * h);
+
+ switch (cl->preferredEncoding) {
+ case rfbEncodingRaw:
+ if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingRRE:
+ if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingCoRRE:
+ if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingHextile:
+ if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingZlib:
+ if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ case rfbEncodingTight:
+ if (!rfbSendRectEncodingTight(cl, x, y, w, h)) {
+ REGION_UNINIT(pScreen,&updateRegion);
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ REGION_UNINIT(pScreen,&updateRegion);
+
+ if (nUpdateRegionRects == 0xFFFF && !rfbSendLastRectMarker(cl))
+ return FALSE;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+/*
+ * Send the copy region as a string of CopyRect encoded rectangles.
+ * The only slightly tricky thing is that we should send the messages in
+ * the correct order so that an earlier CopyRect will not corrupt the source
+ * of a later one.
+ */
+
+static Bool
+rfbSendCopyRegion(cl, reg, dx, dy)
+ rfbClientPtr cl;
+ RegionPtr reg;
+ int dx, dy;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int nrects, nrectsInBand, x_inc, y_inc, thisRect, firstInNextBand;
+ int x, y, w, h;
+ rfbFramebufferUpdateRectHeader rect;
+ rfbCopyRect cr;
+
+ nrects = REGION_NUM_RECTS(reg);
+
+ if (dx <= 0) {
+ x_inc = 1;
+ } else {
+ x_inc = -1;
+ }
+
+ if (dy <= 0) {
+ thisRect = 0;
+ y_inc = 1;
+ } else {
+ thisRect = nrects - 1;
+ y_inc = -1;
+ }
+
+ while (nrects > 0) {
+
+ firstInNextBand = thisRect;
+ nrectsInBand = 0;
+
+ while ((nrects > 0) &&
+ (REGION_RECTS(reg)[firstInNextBand].y1
+ == REGION_RECTS(reg)[thisRect].y1))
+ {
+ firstInNextBand += y_inc;
+ nrects--;
+ nrectsInBand++;
+ }
+
+ if (x_inc != y_inc) {
+ thisRect = firstInNextBand - y_inc;
+ }
+
+ while (nrectsInBand > 0) {
+ if ((pVNC->ublen + sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbCopyRect) > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ x = REGION_RECTS(reg)[thisRect].x1;
+ y = REGION_RECTS(reg)[thisRect].y1;
+ w = REGION_RECTS(reg)[thisRect].x2 - x;
+ h = REGION_RECTS(reg)[thisRect].y2 - y;
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingCopyRect);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cr.srcX = Swap16IfLE(x - dx);
+ cr.srcY = Swap16IfLE(y - dy);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&cr, sz_rfbCopyRect);
+ pVNC->ublen += sz_rfbCopyRect;
+
+ cl->rfbRectanglesSent[rfbEncodingCopyRect]++;
+ cl->rfbBytesSent[rfbEncodingCopyRect]
+ += sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect;
+
+ thisRect += x_inc;
+ nrectsInBand--;
+ }
+
+ thisRect = firstInNextBand;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Send a given rectangle in raw encoding (rfbEncodingRaw).
+ */
+
+Bool
+rfbSendRectEncodingRaw(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+ int nlines;
+ int bytesPerLine = w * (cl->format.bitsPerPixel / 8);
+ int newy = y;
+
+ /* Flush the buffer to guarantee correct alignment for translateFn(). */
+ if (pVNC->ublen > 0) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingRaw);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingRaw]++;
+ cl->rfbBytesSent[rfbEncodingRaw]
+ += sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h;
+
+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine;
+
+ while (TRUE) {
+ if (nlines > h)
+ nlines = h;
+
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat,
+ &cl->format, &pVNC->updateBuf[pVNC->ublen],
+ pVNC->paddedWidthInBytes, w, nlines, x, newy);
+
+ pVNC->ublen += nlines * bytesPerLine;
+ h -= nlines;
+ newy += nlines;
+
+ if (h == 0) /* rect fitted in buffer, do next one */
+ return TRUE;
+
+ /* buffer full - flush partial rect and do another nlines */
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ nlines = (UPDATE_BUF_SIZE - pVNC->ublen) / bytesPerLine;
+ if (nlines == 0) {
+ rfbLog("rfbSendRectEncodingRaw: send buffer too small for %d "
+ "bytes per line\n", bytesPerLine);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+ }
+}
+
+
+/*
+ * Send an empty rectangle with encoding field set to value of
+ * rfbEncodingLastRect to notify client that this is the last
+ * rectangle in framebuffer update ("LastRect" extension of RFB
+ * protocol).
+ */
+
+static Bool
+rfbSendLastRectMarker(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingLastRect);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = 0;
+ rect.r.h = 0;
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbLastRectMarkersSent++;
+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
+
+ return TRUE;
+}
+
+
+/*
+ * Send the contents of pVNC->updateBuf. Returns 1 if successful, -1 if
+ * not (errno should be set).
+ */
+
+Bool
+rfbSendUpdateBuf(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+
+ /*
+ int i;
+ for (i = 0; i < pVNC->ublen; i++) {
+ rfbLog("%02x ",((unsigned char *)pVNC->updateBuf)[i]);
+ }
+ rfbLog("\n");
+ */
+
+ if (pVNC->ublen > 0 && WriteExact(cl->sock, (char*)pVNC->updateBuf, pVNC->ublen) < 0) {
+ rfbLogPerror("rfbSendUpdateBuf: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ pVNC->ublen = 0;
+ return TRUE;
+}
+
+
+
+/*
+ * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the
+ * client, using values from the currently installed colormap.
+ */
+
+Bool
+rfbSendSetColourMapEntries(cl, firstColour, nColours)
+ rfbClientPtr cl;
+ int firstColour;
+ int nColours;
+{
+#if !XFREE86VNC
+ VNCSCREENPTR(cl->pScreen);
+#endif
+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]);
+ EntryPtr pent;
+ EntryPtr redEntry, greenEntry, blueEntry;
+ unsigned short redPart, greenPart, bluePart;
+ int i, len;
+
+ scme->type = rfbSetColourMapEntries;
+ scme->nColours = Swap16IfLE(nColours);
+
+ len = sz_rfbSetColourMapEntriesMsg;
+
+ /* PseudoColor */
+#if XFREE86VNC
+ if (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor) {
+#else
+ if (pVNC->rfbInstalledColormap->class == PseudoColor) {
+#endif
+ scme->firstColour = Swap16IfLE(firstColour);
+#if XFREE86VNC
+ pent = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[firstColour];
+#else
+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[firstColour];
+#endif
+ for (i = 0; i < nColours; i++) {
+ if (pent->fShared) {
+ rgb[i*3] = Swap16IfLE(pent->co.shco.red->color);
+ rgb[i*3+1] = Swap16IfLE(pent->co.shco.green->color);
+ rgb[i*3+2] = Swap16IfLE(pent->co.shco.blue->color);
+ } else {
+ rgb[i*3] = Swap16IfLE(pent->co.local.red);
+ rgb[i*3+1] = Swap16IfLE(pent->co.local.green);
+ rgb[i*3+2] = Swap16IfLE(pent->co.local.blue);
+ }
+ pent++;
+ }
+ }
+
+ else {
+
+ /* Break the DirectColor pixel into its r/g/b components */
+#if XFREE86VNC
+ redPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->redMask)
+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetRed;
+ greenPart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->greenMask)
+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetGreen;
+ bluePart = (firstColour & miInstalledMaps[cl->pScreen->myNum]->pVisual->blueMask)
+ >> miInstalledMaps[cl->pScreen->myNum]->pVisual->offsetBlue;
+#else
+ redPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->redMask)
+ >> pVNC->rfbInstalledColormap->pVisual->offsetRed;
+ greenPart = (firstColour & pVNC->rfbInstalledColormap->pVisual->greenMask)
+ >> pVNC->rfbInstalledColormap->pVisual->offsetGreen;
+ bluePart = (firstColour & pVNC->rfbInstalledColormap->pVisual->blueMask)
+ >> pVNC->rfbInstalledColormap->pVisual->offsetBlue;
+#endif
+
+ /*
+ * The firstColour field is only 16 bits. To support 24-bit pixels we
+ * sneak the red component in the 8-bit padding field which we renamed
+ * to redIndex. Green and blue are in firstColour (MSB, LSB respectively).
+ */
+ scme->redIndex = Swap16IfLE(redPart);
+ scme->firstColour = Swap16IfLE((greenPart << 8) | bluePart);
+
+#if XFREE86VNC
+ redEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->red[redPart];
+ greenEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->green[greenPart];
+ blueEntry = (EntryPtr)&miInstalledMaps[cl->pScreen->myNum]->blue[bluePart];
+#else
+ redEntry = (EntryPtr)&pVNC->rfbInstalledColormap->red[redPart];
+ greenEntry = (EntryPtr)&pVNC->rfbInstalledColormap->green[greenPart];
+ blueEntry = (EntryPtr)&pVNC->rfbInstalledColormap->blue[bluePart];
+#endif
+ for (i = 0; i < nColours; i++) {
+ if (redEntry->fShared)
+ rgb[i*3] = Swap16IfLE(redEntry->co.shco.red->color);
+ else
+ rgb[i*3] = Swap16IfLE(redEntry->co.local.red);
+
+ if (greenEntry->fShared)
+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.shco.green->color);
+ else
+ rgb[i*3+1] = Swap16IfLE(greenEntry->co.local.green);
+
+ if (blueEntry->fShared)
+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.shco.blue->color);
+ else
+ rgb[i*3+2] = Swap16IfLE(blueEntry->co.local.blue);
+
+ redEntry++;
+ greenEntry++;
+ blueEntry++;
+ }
+ }
+
+ len += nColours * 3 * 2;
+
+ if (WriteExact(cl->sock, buf, len) < 0) {
+ rfbLogPerror("rfbSendSetColourMapEntries: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*
+ * rfbSendBell sends a Bell message to all the clients.
+ */
+
+void
+rfbSendBell(void)
+{
+ rfbClientPtr cl, nextCl;
+ rfbBellMsg b;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ b.type = rfbBell;
+ if (WriteExact(cl->sock, (char *)&b, sz_rfbBellMsg) < 0) {
+ rfbLogPerror("rfbSendBell: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+ }
+}
+
+#ifdef CHROMIUM
+#ifdef sun
+extern int inet_aton(const char *cp, struct in_addr *inp);
+#endif
+
+
+/**
+ * This sends a ChromiumStart message to all VNC viewers running on the
+ * host named by ipaddress.
+ * This is done in response to an OpenGL/Chromium app calling
+ * XVncChromiumStart().
+ */
+void
+rfbSendChromiumStart(unsigned int ipaddress, unsigned int crServerPort,
+ unsigned int mothershipPort)
+{
+ rfbClientPtr cl, nextCl;
+ rfbChromiumStartMsg scd;
+ struct in_addr ip;
+ unsigned int vncipaddress;
+
+ /*rfbLog("Enter %s\n", __func__);*/
+ /* loop over vnc viewers/clients */
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ /*rfbLog("%s: cl=%p enableCr=%d\n", __func__,
+ (void*) cl, cl->enableChromiumEncoding);
+ */
+ if (!cl->enableChromiumEncoding) {
+ /* viewer is not chromium-enhanced */
+ continue;
+ }
+ inet_aton(cl->host, &ip);
+ memcpy(&vncipaddress, &ip, sizeof(unsigned int));
+ rfbLog("%s: ipaddr=0x%x vncipaddr=0x%x cl->port=%d\n",
+ __func__, ipaddress, vncipaddress, cl->chromium_port);
+ if (ipaddress == vncipaddress /**&& !cl->chromium_port**/) {
+ cl->chromium_port = crServerPort;
+ cl->chromium_msport = mothershipPort;
+ scd.type = rfbChromiumStart;
+ scd.crServerPort = crServerPort;
+ scd.mothershipPort = mothershipPort;
+ if (WriteExact(cl->sock, (char *)&scd,
+ sz_rfbChromiumStartMsg) < 0) {
+ rfbLogPerror("rfbSendChromiumStart: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+ /* We only start one client at a time, so break now! */
+ break;
+ }
+ }
+ /*rfbLog("Leave %s\n", __func__);*/
+}
+
+
+/**
+ * Begin monitoring the given X windowid.
+ * When we detect size/position/visibility changes we'll send a
+ * rfbChromiumMoveResizeWindow, rfbChromiumClipList, or rfbChromiumWindowShow
+ * message to the VNC viewer, passing the corresponding Chromium window id.
+ */
+void
+rfbChromiumMonitorWindowID(unsigned int cr_windowid, unsigned long xwindowid)
+{
+ CRWindowTable *newRec, *wt, *nextWt = NULL;
+
+ if (xwindowid && !cr_windowid) {
+ /* stop monitoring the X window, remove from list */
+ CRWindowTable *prev = NULL;
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (wt->XwinId == xwindowid) {
+ /* remove */
+ if (prev)
+ prev->next = wt->next;
+ else
+ windowTable = wt->next;
+ xfree(wt);
+ }
+ else {
+ prev = wt;
+ }
+ }
+ return;
+ }
+
+ /* See if we're already monitoring this window */
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ /* and if so, update it's window ID */
+ if (wt->CRwinId == cr_windowid) {
+ wt->XwinId = xwindowid;
+ return;
+ }
+ }
+
+ /* o.k, new window so create new slot information */
+ newRec = (CRWindowTable *)xalloc(sizeof(CRWindowTable));
+ if (!newRec) {
+ rfbLog("Out of memory allocating CRWindowTable.\n");
+ return;
+ }
+
+ newRec->next = NULL;
+ newRec->CRwinId = cr_windowid;
+ newRec->XwinId = xwindowid;
+ newRec->clipRects = NULL;
+ newRec->numRects = 0;
+
+ if (!windowTable) {
+ windowTable = newRec;
+ }
+ else {
+ for (wt = windowTable; wt; wt = nextWt) {
+ nextWt = wt->next;
+ if (!wt->next) /* found the next slot */
+ wt->next = newRec;
+ }
+ }
+}
+
+
+void
+rfbSendChromiumMoveResizeWindow(unsigned int winid, int x, int y, unsigned int w, unsigned int h)
+{
+ rfbClientPtr cl, nextCl;
+ rfbChromiumMoveResizeWindowMsg scm;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ if (!cl->enableChromiumEncoding)
+ continue;
+ if (cl->chromium_port) {
+ scm.type = rfbChromiumMoveResizeWindow;
+ scm.winid = winid;
+ scm.x = x;
+ scm.y = y;
+ scm.w = w;
+ scm.h = h;
+ if (WriteExact(cl->sock, (char *)&scm,
+ sz_rfbChromiumMoveResizeWindowMsg) < 0) {
+ rfbLogPerror("rfbSendChromiumMoveResizeWindow: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ }
+ }
+}
+
+void
+rfbSendChromiumClipList(unsigned int winid, BoxPtr pClipRects, int numClipRects)
+{
+ rfbClientPtr cl, nextCl;
+ rfbChromiumClipListMsg sccl;
+ int len = sizeof(BoxRec) * numClipRects;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ if (!cl->enableChromiumEncoding)
+ continue;
+ if (cl->chromium_port) {
+ sccl.type = rfbChromiumClipList;
+ sccl.winid = winid;
+ sccl.length = Swap32IfLE(len);
+ if (WriteExact(cl->sock, (char *)&sccl,
+ sz_rfbChromiumClipListMsg) < 0) {
+ rfbLogPerror("rfbSendChromiumClipList: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ if (WriteExact(cl->sock, (char *)pClipRects, len) < 0) {
+ rfbLogPerror("rfbSendChromiumClipList: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ }
+ }
+}
+
+void
+rfbSendChromiumWindowShow(unsigned int winid, unsigned int show)
+{
+ rfbClientPtr cl, nextCl;
+ rfbChromiumWindowShowMsg scws;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ if (!cl->enableChromiumEncoding)
+ continue;
+ if (cl->chromium_port) {
+ scws.type = rfbChromiumWindowShow;
+ scws.winid = winid;
+ scws.show = show;
+ if (WriteExact(cl->sock, (char *)&scws,
+ sz_rfbChromiumWindowShowMsg) < 0) {
+ rfbLogPerror("rfbSendChromiumWindowShow: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ }
+ }
+}
+
+void
+rfbSendChromiumWindowDestroy(unsigned int winid)
+{
+ rfbClientPtr cl, nextCl;
+ rfbChromiumWindowDestroyMsg scwd;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ if (!cl->enableChromiumEncoding)
+ continue;
+ if (cl->chromium_port) {
+ scwd.type = rfbChromiumWindowDestroy;
+ scwd.winid = winid;
+ if (WriteExact(cl->sock, (char *)&scwd,
+ sz_rfbChromiumWindowDestroyMsg) < 0) {
+ rfbLogPerror("rfbSendChromiumWindowDestroy: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ }
+ }
+}
+#endif /* CHROMIUM */
+
+/*
+ * rfbSendServerCutText sends a ServerCutText message to all the clients.
+ */
+
+void
+rfbSendServerCutText(char *str, int len)
+{
+ rfbClientPtr cl, nextCl = NULL;
+ rfbServerCutTextMsg sct;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ if (cl->state != RFB_NORMAL) continue;
+ nextCl = cl->next;
+ sct.type = rfbServerCutText;
+ sct.length = Swap32IfLE(len);
+ if (WriteExact(cl->sock, (char *)&sct,
+ sz_rfbServerCutTextMsg) < 0) {
+ rfbLogPerror("rfbSendServerCutText: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ continue;
+ }
+ if (WriteExact(cl->sock, str, len) < 0) {
+ rfbLogPerror("rfbSendServerCutText: write\n");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ }
+ }
+}
+
+
+
+
+/*****************************************************************************
+ *
+ * UDP can be used for keyboard and pointer events when the underlying
+ * network is highly reliable. This is really here to support ORL's
+ * videotile, whose TCP implementation doesn't like sending lots of small
+ * packets (such as 100s of pen readings per second!).
+ */
+
+void
+rfbNewUDPConnection(sock)
+ int sock;
+{
+ if (write(sock, &ptrAcceleration, 1) < 0) {
+ rfbLogPerror("rfbNewUDPConnection: write");
+ }
+}
+
+/*
+ * Because UDP is a message based service, we can't read the first byte and
+ * then the rest of the packet separately like we do with TCP. We will always
+ * get a whole packet delivered in one go, so we ask read() for the maximum
+ * number of bytes we can possibly get.
+ */
+
+void
+rfbProcessUDPInput(ScreenPtr pScreen, int sock)
+{
+ VNCSCREENPTR(pScreen);
+ int n;
+ rfbClientToServerMsg msg;
+
+ if ((n = read(sock, (char *)&msg, sizeof(msg))) <= 0) {
+ if (n < 0) {
+ rfbLogPerror("rfbProcessUDPInput: read");
+ }
+ rfbDisconnectUDPSock(pScreen);
+ return;
+ }
+
+ switch (msg.type) {
+
+ case rfbKeyEvent:
+ if (n != sz_rfbKeyEventMsg) {
+ rfbLog("rfbProcessUDPInput: key event incorrect length\n");
+ rfbDisconnectUDPSock(pScreen);
+ return;
+ }
+ if (!pVNC->rfbViewOnly) {
+ KbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), 0);
+ }
+ break;
+
+ case rfbPointerEvent:
+ if (n != sz_rfbPointerEventMsg) {
+ rfbLog("rfbProcessUDPInput: ptr event incorrect length\n");
+ rfbDisconnectUDPSock(pScreen);
+ return;
+ }
+ if (!pVNC->rfbViewOnly) {
+ PtrAddEvent(msg.pe.buttonMask,
+ Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), 0);
+ }
+ break;
+
+ default:
+ rfbLog("rfbProcessUDPInput: unknown message type %d\n",
+ msg.type);
+ rfbDisconnectUDPSock(pScreen);
+ }
+}
--- xorg-server-1.7.4/hw/vnc/rre.c
+++ xorg-server-1.7.4/hw/vnc/rre.c
@@ -0,0 +1,324 @@
+/*
+ * rre.c
+ *
+ * Routines to implement Rise-and-Run-length Encoding (RRE). This
+ * code is based on krw's original javatel rfbserver.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include "rfb.h"
+
+/*
+ * rreBeforeBuf contains pixel data in the client's format.
+ * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is
+ * larger than the raw data or if it exceeds rreAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int rreBeforeBufSize = 0;
+static unsigned char *rreBeforeBuf = NULL;
+
+static int rreAfterBufSize = 0;
+static unsigned char *rreAfterBuf = NULL;
+static int rreAfterBufLen;
+
+static int subrectEncode8(CARD8 *data, int w, int h);
+static int subrectEncode16(CARD16 *data, int w, int h);
+static int subrectEncode32(CARD32 *data, int w, int h);
+static CARD32 getBgColour(char *data, int size, int bpp);
+
+
+/*
+ * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding.
+ */
+
+Bool
+rfbSendRectEncodingRRE(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+ rfbRREHeader hdr;
+ int nSubrects;
+ int i;
+ int maxRawSize = (pVNC->width * pVNC->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (rreBeforeBufSize < maxRawSize) {
+ rreBeforeBufSize = maxRawSize;
+ if (rreBeforeBuf == NULL)
+ rreBeforeBuf = (unsigned char *)xalloc(rreBeforeBufSize);
+ else
+ rreBeforeBuf = (unsigned char *)xrealloc(rreBeforeBuf, rreBeforeBufSize);
+ }
+
+ if (rreAfterBufSize < maxRawSize) {
+ rreAfterBufSize = maxRawSize;
+ if (rreAfterBuf == NULL)
+ rreAfterBuf = (unsigned char *)xalloc(rreAfterBufSize);
+ else
+ rreAfterBuf = (unsigned char *)xrealloc(rreAfterBuf, rreAfterBufSize);
+ }
+
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable,
+ &pVNC->rfbServerFormat,
+ &cl->format, rreBeforeBuf,
+ pVNC->paddedWidthInBytes, w, h, x, y);
+
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ nSubrects = subrectEncode8((CARD8 *)rreBeforeBuf, w, h);
+ break;
+ case 16:
+ nSubrects = subrectEncode16((CARD16 *)rreBeforeBuf, w, h);
+ break;
+ case 32:
+ nSubrects = subrectEncode32((CARD32 *)rreBeforeBuf, w, h);
+ break;
+ default:
+ rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel);
+ exit(1);
+ }
+
+ if (nSubrects < 0) {
+
+ /* RRE encoding was too large, use raw */
+
+ return rfbSendRectEncodingRaw(cl, x, y, w, h);
+ }
+
+ cl->rfbRectanglesSent[rfbEncodingRRE]++;
+ cl->rfbBytesSent[rfbEncodingRRE] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbRREHeader + rreAfterBufLen);
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingRRE);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nSubrects = Swap32IfLE(nSubrects);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbRREHeader);
+ pVNC->ublen += sz_rfbRREHeader;
+
+ for (i = 0; i < rreAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen;
+
+ if (i + bytesToCopy > rreAfterBufLen) {
+ bytesToCopy = rreAfterBufLen - i;
+ }
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], &rreAfterBuf[i], bytesToCopy);
+
+ pVNC->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (pVNC->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * subrectEncode() encodes the given multicoloured rectangle as a background
+ * colour overwritten by single-coloured rectangles. It returns the number
+ * of subrectangles in the encoded buffer, or -1 if subrect encoding won't
+ * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The
+ * single-colour rectangle partition is not optimal, but does find the biggest
+ * horizontal or vertical rectangle top-left anchored to each consecutive
+ * coordinate position.
+ *
+ * The coding scheme is simply [<bgcolour><subrect><subrect>...] where each
+ * <subrect> is [<colour><x><y><w><h>].
+ */
+
+#define DEFINE_SUBRECT_ENCODE(bpp) \
+static int \
+subrectEncode##bpp(data,w,h) \
+ CARD##bpp *data; \
+ int w; \
+ int h; \
+{ \
+ CARD##bpp cl; \
+ rfbRectangle subrect; \
+ int x,y; \
+ int i,j; \
+ int hx=0,hy,vx=0,vy; \
+ int hyflag; \
+ CARD##bpp *seg; \
+ CARD##bpp *line; \
+ int hw,hh,vw,vh; \
+ int thex,they,thew,theh; \
+ int numsubs = 0; \
+ int newLen; \
+ CARD##bpp bg = (CARD##bpp)getBgColour((char*)data,w*h,bpp); \
+ \
+ *((CARD##bpp*)rreAfterBuf) = bg; \
+ \
+ rreAfterBufLen = (bpp/8); \
+ \
+ for (y=0; y<h; y++) { \
+ line = data+(y*w); \
+ for (x=0; x<w; x++) { \
+ if (line[x] != bg) { \
+ cl = line[x]; \
+ hy = y-1; \
+ hyflag = 1; \
+ for (j=y; j<h; j++) { \
+ seg = data+(j*w); \
+ if (seg[x] != cl) {break;} \
+ i = x; \
+ while ((seg[i] == cl) && (i < w)) i += 1; \
+ i -= 1; \
+ if (j == y) vx = hx = i; \
+ if (i < vx) vx = i; \
+ if ((hyflag > 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \
+ } \
+ vy = j-1; \
+ \
+ /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \
+ * We'll choose the bigger of the two. \
+ */ \
+ hw = hx-x+1; \
+ hh = hy-y+1; \
+ vw = vx-x+1; \
+ vh = vy-y+1; \
+ \
+ thex = x; \
+ they = y; \
+ \
+ if ((hw*hh) > (vw*vh)) { \
+ thew = hw; \
+ theh = hh; \
+ } else { \
+ thew = vw; \
+ theh = vh; \
+ } \
+ \
+ subrect.x = Swap16IfLE(thex); \
+ subrect.y = Swap16IfLE(they); \
+ subrect.w = Swap16IfLE(thew); \
+ subrect.h = Swap16IfLE(theh); \
+ \
+ newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \
+ if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \
+ return -1; \
+ \
+ numsubs += 1; \
+ *((CARD##bpp*)(rreAfterBuf + rreAfterBufLen)) = cl; \
+ rreAfterBufLen += (bpp/8); \
+ memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \
+ rreAfterBufLen += sz_rfbRectangle; \
+ \
+ /* \
+ * Now mark the subrect as done. \
+ */ \
+ for (j=they; j < (they+theh); j++) { \
+ for (i=thex; i < (thex+thew); i++) { \
+ data[j*w+i] = bg; \
+ } \
+ } \
+ } \
+ } \
+ } \
+ \
+ return numsubs; \
+}
+
+DEFINE_SUBRECT_ENCODE(8)
+DEFINE_SUBRECT_ENCODE(16)
+DEFINE_SUBRECT_ENCODE(32)
+
+
+/*
+ * getBgColour() gets the most prevalent colour in a byte array.
+ */
+static CARD32
+getBgColour(data,size,bpp)
+ char *data;
+ int size;
+ int bpp;
+{
+
+#define NUMCLRS 256
+
+ static int counts[NUMCLRS];
+ int i,j,k;
+
+ int maxcount = 0;
+ CARD8 maxclr = 0;
+
+ if (bpp != 8) {
+ if (bpp == 16) {
+ return ((CARD16 *)data)[0];
+ } else if (bpp == 32) {
+ return ((CARD32 *)data)[0];
+ } else {
+ rfbLog("getBgColour: bpp %d?\n",bpp);
+ exit(1);
+ }
+ }
+
+ for (i=0; i<NUMCLRS; i++) {
+ counts[i] = 0;
+ }
+
+ for (j=0; j<size; j++) {
+ k = (int)(((CARD8 *)data)[j]);
+ if (k >= NUMCLRS) {
+ rfbLog("getBgColour: unusual colour = %d\n", k);
+ exit(1);
+ }
+ counts[k] += 1;
+ if (counts[k] > maxcount) {
+ maxcount = counts[k];
+ maxclr = ((CARD8 *)data)[j];
+ }
+ }
+
+ return maxclr;
+}
--- xorg-server-1.7.4/hw/vnc/sockets.c
+++ xorg-server-1.7.4/hw/vnc/sockets.c
@@ -0,0 +1,656 @@
+/*
+ * sockets.c - deal with TCP & UDP sockets.
+ *
+ * This code should be independent of any changes in the RFB protocol. It just
+ * deals with the X server scheduling stuff, calling rfbNewClientConnection and
+ * rfbProcessClientMessage to actually deal with the protocol. If a socket
+ * needs to be closed for any reason then rfbCloseSock should be called, and
+ * this in turn will call rfbClientConnectionGone. To make an active
+ * connection out, call rfbConnect - note that this does _not_ call
+ * rfbNewClientConnection.
+ *
+ * This file is divided into two types of function. Those beginning with
+ * "rfb" are specific to sockets using the RFB protocol. Those without the
+ * "rfb" prefix are more general socket routines (which are used by the http
+ * code).
+ *
+ * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN
+ * not EWOULDBLOCK.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "windowstr.h"
+
+#ifndef USE_LIBWRAP
+#define USE_LIBWRAP 0
+#endif
+#if USE_LIBWRAP
+#include <syslog.h>
+#include <tcpd.h>
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+#endif
+
+#include "rfb.h"
+
+int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has
+ gone away - needed to stop us hanging */
+
+static struct sockaddr_in udpRemoteAddr;
+
+/*
+ * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB
+ * connections. It does nothing if called again.
+ */
+
+Bool
+rfbInitSockets(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+
+ if (inetdSock != -1) {
+ const int one = 1;
+
+ if (fcntl(inetdSock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("fcntl");
+ return FALSE;
+ }
+
+ if (setsockopt(inetdSock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("setsockopt");
+ return FALSE;
+ }
+
+ AddEnabledDevice(inetdSock);
+ FD_ZERO(&pVNC->allFds);
+ FD_SET(inetdSock, &pVNC->allFds);
+ pVNC->maxFd = inetdSock;
+ return TRUE;
+ }
+
+ if (pVNC->rfbPort == 0) {
+ pVNC->rfbPort = 5900 + atoi(display) + pScreen->myNum;
+ }
+
+ if ((pVNC->rfbListenSock = ListenOnTCPPort(pScreen, pVNC->rfbPort)) < 0) {
+ rfbLogPerror("ListenOnTCPPort");
+ pVNC->rfbPort = 0;
+ return FALSE;
+ }
+
+ rfbLog("Listening for VNC connections on TCP port %d\n", pVNC->rfbPort);
+
+ AddEnabledDevice(pVNC->rfbListenSock);
+
+ FD_ZERO(&pVNC->allFds);
+ FD_SET(pVNC->rfbListenSock, &pVNC->allFds);
+ pVNC->maxFd = pVNC->rfbListenSock;
+
+ if (pVNC->udpPort != 0) {
+ rfbLog("rfbInitSockets: listening for input on UDP port %d\n",pVNC->udpPort);
+
+ if ((pVNC->udpSock = ListenOnUDPPort(pScreen, pVNC->udpPort)) < 0) {
+ rfbLogPerror("ListenOnUDPPort");
+ return FALSE;
+ }
+ AddEnabledDevice(pVNC->udpSock);
+ FD_SET(pVNC->udpSock, &pVNC->allFds);
+ pVNC->maxFd = max(pVNC->udpSock,pVNC->maxFd);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB
+ * socket(s). If there is input to process, the appropriate function in the
+ * RFB server code will be called (rfbNewClientConnection,
+ * rfbProcessClientMessage, etc).
+ */
+
+void
+rfbCheckFds(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+#if XFREE86VNC
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+#endif
+ int nfds;
+ fd_set fds;
+ struct timeval tv;
+ struct sockaddr_in addr;
+ SOCKLEN_T addrlen = sizeof(addr);
+ char buf[6];
+ const int one = 1;
+ int sock;
+ static Bool inetdInitDone = FALSE;
+
+ if (!inetdInitDone && inetdSock != -1) {
+ rfbNewClientConnection(pScreen, inetdSock);
+ inetdInitDone = TRUE;
+ }
+
+ memcpy((char *)&fds, (char *)&pVNC->allFds, sizeof(fd_set));
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ nfds = select(pVNC->maxFd + 1, &fds, NULL, NULL, &tv);
+ if (nfds == 0) {
+ return;
+ }
+ if (nfds < 0) {
+ if (errno != EINTR)
+ rfbLogPerror("rfbCheckFds: select");
+ return;
+ }
+
+ if (pVNC->rfbListenSock != -1 && FD_ISSET(pVNC->rfbListenSock, &fds)) {
+
+ if ((sock = accept(pVNC->rfbListenSock,
+ (struct sockaddr *)&addr, &addrlen)) < 0) {
+ rfbLogPerror("rfbCheckFds: accept");
+ return;
+ }
+
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("rfbCheckFds: fcntl");
+ close(sock);
+ return;
+ }
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("rfbCheckFds: setsockopt");
+ close(sock);
+ return;
+ }
+
+ rfbLog("\n");
+
+#if USE_LIBWRAP
+ if (!hosts_ctl("Xvnc", STRING_UNKNOWN, inet_ntoa(addr.sin_addr),
+ STRING_UNKNOWN)) {
+ rfbLog("Rejected connection from client %s\n",
+ inet_ntoa(addr.sin_addr));
+ close(sock);
+ return;
+ }
+#endif
+
+ rfbLog("Got VNC connection from client %s\n", inet_ntoa(addr.sin_addr));
+
+ AddEnabledDevice(sock);
+ FD_SET(sock, &pVNC->allFds);
+ pVNC->maxFd = max(sock,pVNC->maxFd);
+
+ rfbNewClientConnection(pScreen, sock);
+
+ FD_CLR(pVNC->rfbListenSock, &fds);
+ if (--nfds == 0)
+ return;
+ }
+
+ if ((pVNC->udpSock != -1) && FD_ISSET(pVNC->udpSock, &fds)) {
+
+ if (recvfrom(pVNC->udpSock, buf, 1, MSG_PEEK,
+ (struct sockaddr *)&addr, &addrlen) < 0) {
+
+ rfbLogPerror("rfbCheckFds: UDP: recvfrom");
+ rfbDisconnectUDPSock(pScreen);
+
+ } else {
+
+ if (!pVNC->udpSockConnected ||
+ (memcmp(&addr, &udpRemoteAddr, addrlen) != 0))
+ {
+ /* new remote end */
+ rfbLog("rfbCheckFds: UDP: got connection\n");
+
+ memcpy(&udpRemoteAddr, &addr, addrlen);
+ pVNC->udpSockConnected = TRUE;
+
+ if (connect(pVNC->udpSock,
+ (struct sockaddr *)&addr, addrlen) < 0) {
+ rfbLogPerror("rfbCheckFds: UDP: connect");
+ rfbDisconnectUDPSock(pScreen);
+ return;
+ }
+
+ rfbNewUDPConnection(pVNC->udpSock);
+ }
+
+ rfbProcessUDPInput(pScreen, pVNC->udpSock);
+ }
+
+ FD_CLR(pVNC->udpSock, &fds);
+ if (--nfds == 0)
+ return;
+ }
+
+ for (sock = 0; sock <= pVNC->maxFd; sock++) {
+ if (FD_ISSET(sock, &fds) && FD_ISSET(sock, &pVNC->allFds)) {
+#if XFREE86VNC
+ if (!pScrn->vtSema)
+ rfbCloseSock(pScreen, sock);
+ else
+#endif
+ rfbProcessClientMessage(pScreen, sock);
+ }
+ }
+}
+
+
+void
+rfbDisconnectUDPSock(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+ pVNC->udpSockConnected = FALSE;
+}
+
+
+void
+rfbCloseSock(ScreenPtr pScreen, int sock)
+{
+ VNCSCREENPTR(pScreen);
+ close(sock);
+ RemoveEnabledDevice(sock);
+ FD_CLR(sock, &pVNC->allFds);
+ rfbClientConnectionGone(sock);
+ if (sock == inetdSock)
+ GiveUp(0);
+}
+
+#if 0
+/*
+ * rfbWaitForClient can be called to wait for the RFB client to send us a
+ * message. When one is received it is processed by calling
+ * rfbProcessClientMessage().
+ */
+
+void
+rfbWaitForClient(sock)
+ int sock;
+{
+ int n;
+ fd_set fds;
+ struct timeval tv;
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = rfbMaxClientWait / 1000;
+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000;
+ n = select(sock+1, &fds, NULL, NULL, &tv);
+ if (n < 0) {
+ rfbLogPerror("rfbWaitForClient: select");
+ exit(1);
+ }
+ if (n == 0) {
+ rfbCloseSock(sock);
+ return;
+ }
+
+ rfbProcessClientMessage(sock);
+}
+#endif
+
+/*
+ * rfbConnect is called to make a connection out to a given TCP address.
+ */
+
+int
+rfbConnect(ScreenPtr pScreen, char *host, int port)
+{
+ VNCSCREENPTR(pScreen);
+ int sock;
+ int one = 1;
+
+ rfbLog("\n");
+ rfbLog("Making connection to client on host %s port %d\n",
+ host,port);
+
+ if ((sock = ConnectToTcpAddr(host, port)) < 0) {
+ rfbLogPerror("connection failed");
+ return -1;
+ }
+
+ if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+ rfbLogPerror("fcntl failed");
+ close(sock);
+ return -1;
+ }
+
+ if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
+ (char *)&one, sizeof(one)) < 0) {
+ rfbLogPerror("setsockopt failed");
+ close(sock);
+ return -1;
+ }
+
+ AddEnabledDevice(sock);
+ FD_SET(sock, &pVNC->allFds);
+ pVNC->maxFd = max(sock,pVNC->maxFd);
+
+ return sock;
+}
+
+
+
+
+/*
+ * ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if
+ * those bytes have been read, 0 if the other end has closed, or -1 if an error
+ * occurred (errno is set to ETIMEDOUT if it timed out).
+ */
+
+int
+ReadExact(sock, buf, len)
+ int sock;
+ char *buf;
+ int len;
+{
+ int n;
+ fd_set fds;
+ int tries = 5;
+ struct timeval tv;
+
+ while (len > 0) {
+ n = read(sock, buf, len);
+
+ if (n > 0) {
+
+ buf += n;
+ len -= n;
+
+ } else if (n == 0) {
+
+ return 0;
+
+ } else {
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ return n;
+ }
+
+ do {
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = rfbMaxClientWait / 1000;
+ tv.tv_usec = (rfbMaxClientWait % 1000) * 1000;
+ n = select(sock+1, &fds, NULL, NULL, &tv);
+ tries--;
+
+ /* We really need to retry if we get EINTR, so spin */
+ /* If after 5 attempts we're still broke, abort.... */
+
+ } while ((n < 0 && errno == EINTR) && tries > 0);
+
+ if (n < 0) {
+ rfbLogPerror("ReadExact: select");
+ return n;
+ }
+ if (n == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ }
+ }
+ return 1;
+}
+
+
+
+/*
+ * WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if
+ * those bytes have been written, or -1 if an error occurred (errno is set to
+ * ETIMEDOUT if it timed out).
+ */
+
+int
+WriteExact(sock, buf, len)
+ int sock;
+ char *buf;
+ int len;
+{
+ int n;
+ fd_set fds;
+ struct timeval tv;
+#if 0
+ int totalTimeWaited = 0;
+#endif
+
+ while (len > 0) {
+ n = write(sock, buf, len);
+
+ if (n > 0) {
+
+ buf += n;
+ len -= n;
+
+ } else if (n == 0) {
+
+ rfbLog("WriteExact: write returned 0?\n");
+ return -1;
+
+ } else {
+ if (errno != EWOULDBLOCK && errno != EAGAIN) {
+ return n;
+ }
+
+#if 0
+ /* Retry every 5 seconds until we exceed rfbMaxClientWait. We
+ need to do this because select doesn't necessarily return
+ immediately when the other end has gone away */
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+#else
+ /* We're in the WakeupHandler now, so don't wait */
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+#endif
+ n = select(sock+1, NULL, &fds, NULL, &tv);
+#if 0
+ if (n < 0) {
+ rfbLogPerror("WriteExact: select");
+ return n;
+ }
+ if (n == 0) {
+ totalTimeWaited += 5000;
+ if (totalTimeWaited >= rfbMaxClientWait) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+ } else {
+ totalTimeWaited = 0;
+ }
+#endif
+ }
+ }
+ return 1;
+}
+
+
+int
+ListenOnTCPPort(ScreenPtr pScreen, int port)
+{
+ VNCSCREENPTR(pScreen);
+ struct sockaddr_in addr;
+ int sock;
+ int one = 1;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = pVNC->interface.s_addr;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ return -1;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof(one)) < 0) {
+ close(sock);
+ return -1;
+ }
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ close(sock);
+ return -1;
+ }
+ if (listen(sock, 5) < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+int
+ConnectToTcpAddr(host, port)
+ char *host;
+ int port;
+{
+ struct hostent *hp;
+ int sock, n;
+ struct sockaddr_in addr;
+ int tries = 5;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+
+ if ((addr.sin_addr.s_addr = inet_addr(host)) == -1)
+ {
+ if (!(hp = gethostbyname(host))) {
+ errno = EINVAL;
+ return -1;
+ }
+ addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
+ }
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ return -1;
+ }
+
+ do {
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ tries--;
+
+ /* We really need to retry if we get EINTR, so spin */
+ /* If after 5 attempts we're still broke, abort.... */
+
+ } while ((sock < 0 && errno == EINTR) && tries > 0);
+
+ if (sock < 0) {
+ return -1;
+ }
+
+ tries = 5;
+
+ do {
+ n = connect(sock, (struct sockaddr *)&addr, (sizeof(addr)));
+ tries--;
+
+ /* We really need to retry if we get EINTR, so spin */
+ /* If after 5 attempts we're still broke, abort.... */
+
+ } while ((n < 0 && errno == EINTR) && tries > 0);
+
+ if (n < 0) {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+int
+ListenOnUDPPort(ScreenPtr pScreen, int port)
+{
+ VNCSCREENPTR(pScreen);
+ struct sockaddr_in addr;
+ int sock;
+ int one = 1;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = pVNC->interface.s_addr;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ return -1;
+ }
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&one, sizeof(one)) < 0) {
+ return -1;
+ }
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ return -1;
+ }
+
+ return sock;
+}
+
+#if 0
+/*
+ * rdpInitSockets sets up the TCP for RDP
+ * connections. It does nothing if called again.
+ */
+
+Bool
+rdpInitSockets(ScreenPtr pScreen)
+{
+ VNCSCREENPTR(pScreen);
+
+ if ((pVNC->rdpListenSock = ListenOnTCPPort(pScreen, pVNC->rdpPort)) < 0) {
+ rfbLogPerror("ListenOnTCPPort");
+ pVNC->rdpPort = 0;
+ return FALSE;
+ }
+
+ rfbLog("Listening for RDP connections on TCP port %d\n", pVNC->rdpPort);
+
+ AddEnabledDevice(pVNC->rdpListenSock);
+
+ return TRUE;
+}
+#endif
--- xorg-server-1.7.4/hw/vnc/sprite.c
+++ xorg-server-1.7.4/hw/vnc/sprite.c
@@ -0,0 +1,2279 @@
+/*
+ * sprite.c
+ *
+ * software sprite routines - based on misprite
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/* $XConsortium: misprite.c,v 5.47 94/04/17 20:27:53 dpw Exp $ */
+
+/*
+
+Copyright (c) 1989 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.
+*/
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include "rfb.h"
+# include <X11/X.h>
+# include <X11/Xproto.h>
+# include <X11/fonts/font.h>
+# include <X11/fonts/fontstruct.h>
+# include "misc.h"
+# include "pixmapstr.h"
+# include "input.h"
+# include "mi.h"
+# include "cursorstr.h"
+# include "scrnintstr.h"
+# include "colormapst.h"
+# include "windowstr.h"
+# include "gcstruct.h"
+# include "mipointer.h"
+# include "spritest.h"
+# include "dixfontstr.h"
+
+/*
+ * screen wrappers
+ */
+
+static Bool rfbSpriteCloseScreen(int i, ScreenPtr pScreen);
+static void rfbSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
+ int w, int h, unsigned int format,
+ unsigned long planemask, char *pdstLine);
+static void rfbSpriteGetSpans(DrawablePtr pDrawable, int wMax,
+ DDXPointPtr ppt, int *pwidth, int nspans,
+ char *pdstStart);
+static void rfbSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
+ int width, int height);
+static Bool rfbSpriteCreateGC(GCPtr pGC);
+static void rfbSpriteBlockHandler(int i, pointer blockData,
+ pointer pTimeout,
+ pointer pReadMask);
+static void rfbSpriteInstallColormap(ColormapPtr pMap);
+static void rfbSpriteStoreColors(ColormapPtr pMap, int ndef,
+ xColorItem *pdef);
+
+static void rfbSpritePaintWindowBackground(WindowPtr pWin,
+ RegionPtr pRegion, int what);
+static void rfbSpritePaintWindowBorder(WindowPtr pWin,
+ RegionPtr pRegion, int what);
+static void rfbSpriteCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr pRegion);
+static void rfbSpriteClearToBackground(WindowPtr pWin, int x, int y,
+ int w, int h,
+ Bool generateExposures);
+
+static void rfbSpriteSaveDoomedAreas(WindowPtr pWin,
+ RegionPtr pObscured, int dx,
+ int dy);
+static RegionPtr rfbSpriteRestoreAreas(WindowPtr pWin, RegionPtr pRgnExposed);
+static void rfbSpriteComputeSaved(ScreenPtr pScreen);
+
+static DevPrivateKey rfbSpriteScreenKey = &rfbSpriteScreenKey;
+
+#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
+ ((rfbSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \
+ rfbSpriteScreenKey))->field)
+
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+/*
+ * GC func wrappers
+ */
+
+static void rfbSpriteValidateGC(GCPtr pGC, unsigned long stateChanges,
+ DrawablePtr pDrawable);
+static void rfbSpriteCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void rfbSpriteDestroyGC(GCPtr pGC);
+static void rfbSpriteChangeGC(GCPtr pGC, unsigned long mask);
+static void rfbSpriteChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
+static void rfbSpriteDestroyClip(GCPtr pGC);
+static void rfbSpriteCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+
+static GCFuncs rfbSpriteGCFuncs = {
+ rfbSpriteValidateGC,
+ rfbSpriteChangeGC,
+ rfbSpriteCopyGC,
+ rfbSpriteDestroyGC,
+ rfbSpriteChangeClip,
+ rfbSpriteDestroyClip,
+ rfbSpriteCopyClip,
+};
+
+static DevPrivateKey rfbSpriteGCKey = &rfbSpriteGCKey;
+
+#define GC_FUNC_PROLOGUE(pGC) \
+ rfbSpriteGCPtr pGCPriv = \
+ (rfbSpriteGCPtr)dixLookupPrivate(&(pGC)->devPrivates, rfbSpriteGCKey); \
+ (pGC)->funcs = pGCPriv->wrapFuncs; \
+ if (pGCPriv->wrapOps) \
+ (pGC)->ops = pGCPriv->wrapOps;
+
+#define GC_FUNC_EPILOGUE(pGC) \
+ pGCPriv->wrapFuncs = (pGC)->funcs; \
+ (pGC)->funcs = &rfbSpriteGCFuncs; \
+ if (pGCPriv->wrapOps) \
+ { \
+ pGCPriv->wrapOps = (pGC)->ops; \
+ (pGC)->ops = &rfbSpriteGCOps; \
+ }
+
+/*
+ * GC op wrappers
+ */
+
+static void rfbSpriteFillSpans(DrawablePtr pDrawable, GCPtr pGC,
+ int nInit, DDXPointPtr pptInit,
+ int *pwidthInit, int fSorted);
+static void rfbSpriteSetSpans(DrawablePtr pDrawable, GCPtr pGC,
+ char *psrc, DDXPointPtr ppt, int *pwidth,
+ int nspans, int fSorted);
+static void rfbSpritePutImage(DrawablePtr pDrawable, GCPtr pGC,
+ int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits);
+static RegionPtr rfbSpriteCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w,
+ int h, int dstx, int dsty);
+static RegionPtr rfbSpriteCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w,
+ int h, int dstx, int dsty,
+ unsigned long plane);
+static void rfbSpritePolyPoint(DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, xPoint *pptInit);
+static void rfbSpritePolylines(DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr pptInit);
+static void rfbSpritePolySegment(DrawablePtr pDrawable, GCPtr pGC,
+ int nseg, xSegment *pSegs);
+static void rfbSpritePolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
+ int nrects, xRectangle *pRects);
+static void rfbSpritePolyArc(DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *parcs);
+static void rfbSpriteFillPolygon(DrawablePtr pDrawable, GCPtr pGC,
+ int shape, int mode, int count,
+ DDXPointPtr pPts);
+static void rfbSpritePolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit);
+static void rfbSpritePolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
+ int narcs, xArc *parcs);
+static int rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char *chars);
+static int rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count,
+ unsigned short *chars);
+static void rfbSpriteImageText8(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count, char *chars);
+static void rfbSpriteImageText16(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, int count,
+ unsigned short *chars);
+static void rfbSpriteImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void rfbSpritePolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void rfbSpritePushPixels(GCPtr pGC, PixmapPtr pBitMap,
+ DrawablePtr pDst, int w, int h,
+ int x, int y);
+#ifdef NEED_LINEHELPER
+static void rfbSpriteLineHelper();
+#endif
+
+static GCOps rfbSpriteGCOps = {
+ rfbSpriteFillSpans, rfbSpriteSetSpans, rfbSpritePutImage,
+ rfbSpriteCopyArea, rfbSpriteCopyPlane, rfbSpritePolyPoint,
+ rfbSpritePolylines, rfbSpritePolySegment, rfbSpritePolyRectangle,
+ rfbSpritePolyArc, rfbSpriteFillPolygon, rfbSpritePolyFillRect,
+ rfbSpritePolyFillArc, rfbSpritePolyText8, rfbSpritePolyText16,
+ rfbSpriteImageText8, rfbSpriteImageText16, rfbSpriteImageGlyphBlt,
+ rfbSpritePolyGlyphBlt, rfbSpritePushPixels
+#ifdef NEED_LINEHELPER
+ , rfbSpriteLineHelper
+#endif
+};
+
+/*
+ * testing only -- remove cursor for every draw. Eventually,
+ * each draw operation will perform a bounding box check against
+ * the saved cursor area
+ */
+
+#define GC_SETUP_CHEAP(pDrawable) \
+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr) \
+ dixLookupPrivate(&pDrawable->pScreen->devPrivates, \
+ rfbSpriteScreenKey);
+
+#define GC_SETUP(pDrawable, pGC) \
+ GC_SETUP_CHEAP(pDrawable) \
+ rfbSpriteGCPtr pGCPrivate = \
+ (rfbSpriteGCPtr)dixLookupPrivate(&(pGC)->devPrivates, rfbSpriteGCKey); \
+ GCFuncs *oldFuncs = pGC->funcs;
+
+#define GC_SETUP_AND_CHECK(pDrawable, pGC) \
+ GC_SETUP(pDrawable, pGC); \
+ if (GC_CHECK((WindowPtr)pDrawable)) \
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+
+#define GC_CHECK(pWin) \
+ (pVNC->cursorIsDrawn && \
+ (pScreenPriv->pCacheWin == pWin ? \
+ pScreenPriv->isInCacheWin : ( \
+ (pScreenPriv->pCacheWin = (pWin)) , \
+ (pScreenPriv->isInCacheWin = \
+ (pWin)->drawable.x < pScreenPriv->saved.x2 && \
+ pScreenPriv->saved.x1 < (pWin)->drawable.x + \
+ (int) (pWin)->drawable.width && \
+ (pWin)->drawable.y < pScreenPriv->saved.y2 && \
+ pScreenPriv->saved.y1 < (pWin)->drawable.y + \
+ (int) (pWin)->drawable.height &&\
+ RECT_IN_REGION((pWin)->drawable.pScreen, &(pWin)->borderClip, \
+ &pScreenPriv->saved) != rgnOUT))))
+
+#define GC_OP_PROLOGUE(pGC) { \
+ (pGC)->funcs = pGCPrivate->wrapFuncs; \
+ (pGC)->ops = pGCPrivate->wrapOps; \
+ }
+
+#define GC_OP_EPILOGUE(pGC) { \
+ pGCPrivate->wrapOps = (pGC)->ops; \
+ (pGC)->funcs = oldFuncs; \
+ (pGC)->ops = &rfbSpriteGCOps; \
+ }
+
+/*
+ * pointer-sprite method table
+ */
+
+static Bool rfbSpriteRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor);
+static Bool rfbSpriteUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor);
+static void rfbSpriteSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y);
+static void rfbSpriteMoveCursor (ScreenPtr pScreen, int x, int y);
+
+miPointerSpriteFuncRec rfbSpritePointerFuncs = {
+ rfbSpriteRealizeCursor,
+ rfbSpriteUnrealizeCursor,
+ rfbSpriteSetCursor,
+ rfbSpriteMoveCursor,
+};
+
+/*
+ * other misc functions
+ */
+
+static Bool rfbDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor);
+
+
+/*
+ * rfbSpriteInitialize -- called from device-dependent screen
+ * initialization proc after all of the function pointers have
+ * been stored in the screen structure.
+ */
+
+Bool
+rfbSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
+ ScreenPtr pScreen;
+ rfbSpriteCursorFuncPtr cursorFuncs;
+ miPointerScreenFuncPtr screenFuncs;
+{
+ rfbSpriteScreenPtr pPriv;
+ VisualPtr pVisual;
+
+ if (!dixRequestPrivate(rfbSpriteGCKey, sizeof(rfbSpriteGCRec)))
+ return FALSE;
+
+ pPriv = (rfbSpriteScreenPtr) xalloc (sizeof (rfbSpriteScreenRec));
+ if (!pPriv)
+ return FALSE;
+ if (!miPointerInitialize (pScreen, &rfbSpritePointerFuncs, screenFuncs,TRUE))
+ {
+ xfree ((pointer) pPriv);
+ return FALSE;
+ }
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != pScreen->rootVisual;
+ pVisual++)
+ ;
+ pPriv->pVisual = pVisual;
+ pPriv->CloseScreen = pScreen->CloseScreen;
+ pPriv->GetImage = pScreen->GetImage;
+ pPriv->GetSpans = pScreen->GetSpans;
+ pPriv->SourceValidate = pScreen->SourceValidate;
+ pPriv->CreateGC = pScreen->CreateGC;
+#if 0
+ pPriv->BlockHandler = pScreen->BlockHandler;
+#endif
+ pPriv->InstallColormap = pScreen->InstallColormap;
+ pPriv->StoreColors = pScreen->StoreColors;
+ pPriv->DisplayCursor = pScreen->DisplayCursor;
+
+ pPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
+ pPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
+ pPriv->CopyWindow = pScreen->CopyWindow;
+ pPriv->ClearToBackground = pScreen->ClearToBackground;
+
+ pPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
+ pPriv->RestoreAreas = pScreen->RestoreAreas;
+
+ pPriv->pCursor = NULL;
+ pPriv->x = 0;
+ pPriv->y = 0;
+ pPriv->shouldBeUp = FALSE;
+ pPriv->pCacheWin = NullWindow;
+ pPriv->isInCacheWin = FALSE;
+ pPriv->checkPixels = TRUE;
+ pPriv->pInstalledMap = NULL;
+ pPriv->pColormap = NULL;
+ pPriv->funcs = cursorFuncs;
+ pPriv->colors[SOURCE_COLOR].red = 0;
+ pPriv->colors[SOURCE_COLOR].green = 0;
+ pPriv->colors[SOURCE_COLOR].blue = 0;
+ pPriv->colors[MASK_COLOR].red = 0;
+ pPriv->colors[MASK_COLOR].green = 0;
+ pPriv->colors[MASK_COLOR].blue = 0;
+ dixSetPrivate(&pScreen->devPrivates, rfbSpriteScreenKey, pPriv);
+ pScreen->CloseScreen = rfbSpriteCloseScreen;
+ pScreen->GetImage = rfbSpriteGetImage;
+ pScreen->GetSpans = rfbSpriteGetSpans;
+ pScreen->SourceValidate = rfbSpriteSourceValidate;
+ pScreen->CreateGC = rfbSpriteCreateGC;
+#if 0
+ pScreen->BlockHandler = rfbSpriteBlockHandler;
+#endif
+ pScreen->InstallColormap = rfbSpriteInstallColormap;
+ pScreen->StoreColors = rfbSpriteStoreColors;
+
+ pScreen->PaintWindowBackground = rfbSpritePaintWindowBackground;
+ pScreen->PaintWindowBorder = rfbSpritePaintWindowBorder;
+ pScreen->CopyWindow = rfbSpriteCopyWindow;
+ pScreen->ClearToBackground = rfbSpriteClearToBackground;
+
+ pScreen->SaveDoomedAreas = rfbSpriteSaveDoomedAreas;
+ pScreen->RestoreAreas = rfbSpriteRestoreAreas;
+
+ pScreen->DisplayCursor = rfbDisplayCursor;
+
+ return TRUE;
+}
+
+/*
+ * Screen wrappers
+ */
+
+/*
+ * CloseScreen wrapper -- unwrap everything, free the private data
+ * and call the wrapped function
+ */
+
+static Bool
+rfbSpriteCloseScreen (i, pScreen)
+ ScreenPtr pScreen;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->GetImage = pScreenPriv->GetImage;
+ pScreen->GetSpans = pScreenPriv->GetSpans;
+ pScreen->SourceValidate = pScreenPriv->SourceValidate;
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+#if 0
+ pScreen->BlockHandler = pScreenPriv->BlockHandler;
+#endif
+ pScreen->InstallColormap = pScreenPriv->InstallColormap;
+ pScreen->StoreColors = pScreenPriv->StoreColors;
+
+ pScreen->PaintWindowBackground = pScreenPriv->PaintWindowBackground;
+ pScreen->PaintWindowBorder = pScreenPriv->PaintWindowBorder;
+ pScreen->CopyWindow = pScreenPriv->CopyWindow;
+ pScreen->ClearToBackground = pScreenPriv->ClearToBackground;
+
+ pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
+ pScreen->RestoreAreas = pScreenPriv->RestoreAreas;
+
+ xfree ((pointer) pScreenPriv);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static void
+rfbSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
+ DrawablePtr pDrawable;
+ int sx, sy, w, h;
+ unsigned int format;
+ unsigned long planemask;
+ char *pdstLine;
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, GetImage);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ if (pDrawable->type == DRAWABLE_WINDOW &&
+ pVNC->cursorIsDrawn &&
+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
+ {
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
+ format, planemask, pdstLine);
+
+ SCREEN_EPILOGUE (pScreen, GetImage, rfbSpriteGetImage);
+}
+
+static void
+rfbSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
+ DrawablePtr pDrawable;
+ int wMax;
+ DDXPointPtr ppt;
+ int *pwidth;
+ int nspans;
+ char *pdstStart;
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, GetSpans);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn)
+ {
+ register DDXPointPtr pts;
+ register int *widths;
+ register int nPts;
+ register int xorg,
+ yorg;
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ for (pts = ppt, widths = pwidth, nPts = nspans;
+ nPts--;
+ pts++, widths++)
+ {
+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
+ pts->x+xorg,*widths))
+ {
+ rfbSpriteRemoveCursor (pScreen);
+ break;
+ }
+ }
+ }
+
+ (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+
+ SCREEN_EPILOGUE (pScreen, GetSpans, rfbSpriteGetSpans);
+}
+
+static void
+rfbSpriteSourceValidate (pDrawable, x, y, width, height)
+ DrawablePtr pDrawable;
+ int x, y, width, height;
+{
+ ScreenPtr pScreen = pDrawable->pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, SourceValidate);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ if (pDrawable->type == DRAWABLE_WINDOW && pVNC->cursorIsDrawn &&
+ ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
+ x, y, width, height))
+ {
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ if (pScreen->SourceValidate)
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+
+ SCREEN_EPILOGUE (pScreen, SourceValidate, rfbSpriteSourceValidate);
+}
+
+static Bool
+rfbSpriteCreateGC (pGC)
+ GCPtr pGC;
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ Bool ret;
+ rfbSpriteGCPtr pPriv;
+
+ SCREEN_PROLOGUE (pScreen, CreateGC);
+
+ pPriv = (rfbSpriteGCPtr)dixLookupPrivate(&(pGC)->devPrivates, rfbSpriteGCKey);
+
+ ret = (*pScreen->CreateGC) (pGC);
+
+ pPriv->wrapOps = NULL;
+ pPriv->wrapFuncs = pGC->funcs;
+ pGC->funcs = &rfbSpriteGCFuncs;
+
+ SCREEN_EPILOGUE (pScreen, CreateGC, rfbSpriteCreateGC);
+
+ return ret;
+}
+
+static void
+rfbSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
+ int i;
+ pointer blockData;
+ pointer pTimeout;
+ pointer pReadmask;
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ rfbSpriteScreenPtr pPriv;
+ VNCSCREENPTR(pScreen);
+
+ pPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ SCREEN_PROLOGUE(pScreen, BlockHandler);
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ SCREEN_EPILOGUE(pScreen, BlockHandler, rfbSpriteBlockHandler);
+
+ if (!pVNC->cursorIsDrawn && pPriv->shouldBeUp)
+ rfbSpriteRestoreCursor (pScreen);
+}
+
+static void
+rfbSpriteInstallColormap (pMap)
+ ColormapPtr pMap;
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ rfbSpriteScreenPtr pPriv;
+ VNCSCREENPTR(pScreen);
+
+ pPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ SCREEN_PROLOGUE(pScreen, InstallColormap);
+
+ (*pScreen->InstallColormap) (pMap);
+
+ SCREEN_EPILOGUE(pScreen, InstallColormap, rfbSpriteInstallColormap);
+
+ pPriv->pInstalledMap = pMap;
+ if (pPriv->pColormap != pMap)
+ {
+ pPriv->checkPixels = TRUE;
+ if (pVNC->cursorIsDrawn)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+}
+
+static void
+rfbSpriteStoreColors (pMap, ndef, pdef)
+ ColormapPtr pMap;
+ int ndef;
+ xColorItem *pdef;
+{
+ ScreenPtr pScreen = pMap->pScreen;
+ rfbSpriteScreenPtr pPriv;
+ int i;
+ int updated;
+ VisualPtr pVisual;
+ VNCSCREENPTR(pScreen);
+
+ pPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ SCREEN_PROLOGUE(pScreen, StoreColors);
+
+ (*pScreen->StoreColors) (pMap, ndef, pdef);
+
+ SCREEN_EPILOGUE(pScreen, StoreColors, rfbSpriteStoreColors);
+
+ if (pPriv->pColormap == pMap)
+ {
+ updated = 0;
+ pVisual = pMap->pVisual;
+ if (pVisual->class == DirectColor)
+ {
+ /* Direct color - match on any of the subfields */
+
+#define MaskMatch(a,b,mask) ((a) & ((pVisual->mask) == (b)) & (pVisual->mask))
+
+#define UpdateDAC(plane,dac,mask) {\
+ if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
+ pPriv->colors[plane].dac = pdef[i].dac; \
+ updated = 1; \
+ } \
+}
+
+#define CheckDirect(plane) \
+ UpdateDAC(plane,red,redMask) \
+ UpdateDAC(plane,green,greenMask) \
+ UpdateDAC(plane,blue,blueMask)
+
+ for (i = 0; i < ndef; i++)
+ {
+ CheckDirect (SOURCE_COLOR)
+ CheckDirect (MASK_COLOR)
+ }
+ }
+ else
+ {
+ /* PseudoColor/GrayScale - match on exact pixel */
+ for (i = 0; i < ndef; i++)
+ {
+ if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
+ {
+ pPriv->colors[SOURCE_COLOR] = pdef[i];
+ if (++updated == 2)
+ break;
+ }
+ if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
+ {
+ pPriv->colors[MASK_COLOR] = pdef[i];
+ if (++updated == 2)
+ break;
+ }
+ }
+ }
+ if (updated)
+ {
+ pPriv->checkPixels = TRUE;
+ if (pVNC->cursorIsDrawn)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+ }
+}
+
+static void
+rfbSpriteFindColors (ScreenPtr pScreen)
+{
+ rfbSpriteScreenPtr pScreenPriv = (rfbSpriteScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ CursorPtr pCursor;
+ xColorItem *sourceColor, *maskColor;
+
+ pCursor = pScreenPriv->pCursor;
+ sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
+ maskColor = &pScreenPriv->colors[MASK_COLOR];
+ if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
+ !(pCursor->foreRed == sourceColor->red &&
+ pCursor->foreGreen == sourceColor->green &&
+ pCursor->foreBlue == sourceColor->blue &&
+ pCursor->backRed == maskColor->red &&
+ pCursor->backGreen == maskColor->green &&
+ pCursor->backBlue == maskColor->blue))
+ {
+ pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
+ sourceColor->red = pCursor->foreRed;
+ sourceColor->green = pCursor->foreGreen;
+ sourceColor->blue = pCursor->foreBlue;
+ FakeAllocColor (pScreenPriv->pColormap, sourceColor);
+ maskColor->red = pCursor->backRed;
+ maskColor->green = pCursor->backGreen;
+ maskColor->blue = pCursor->backBlue;
+ FakeAllocColor (pScreenPriv->pColormap, maskColor);
+ /* "free" the pixels right away, don't let this confuse you */
+ FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
+ FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
+ }
+ pScreenPriv->checkPixels = FALSE;
+}
+
+/*
+ * BackingStore wrappers
+ */
+
+static void
+rfbSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
+ WindowPtr pWin;
+ RegionPtr pObscured;
+ int dx, dy;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ BoxRec cursorBox;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pVNC->cursorIsDrawn)
+ {
+ cursorBox = pScreenPriv->saved;
+
+ if (dx || dy)
+ {
+ cursorBox.x1 += dx;
+ cursorBox.y1 += dy;
+ cursorBox.x2 += dx;
+ cursorBox.y2 += dy;
+ }
+ if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
+
+ SCREEN_EPILOGUE (pScreen, SaveDoomedAreas, rfbSpriteSaveDoomedAreas);
+}
+
+static RegionPtr
+rfbSpriteRestoreAreas (pWin, prgnExposed)
+ WindowPtr pWin;
+ RegionPtr prgnExposed;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ RegionPtr result;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, RestoreAreas);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pVNC->cursorIsDrawn)
+ {
+ if (RECT_IN_REGION( pScreen, prgnExposed, &pScreenPriv->saved) != rgnOUT)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
+
+ SCREEN_EPILOGUE (pScreen, RestoreAreas, rfbSpriteRestoreAreas);
+
+ return result;
+}
+
+/*
+ * Window wrappers
+ */
+
+static void
+rfbSpritePaintWindowBackground (pWin, pRegion, what)
+ WindowPtr pWin;
+ RegionPtr pRegion;
+ int what;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, PaintWindowBackground);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pVNC->cursorIsDrawn)
+ {
+ /*
+ * If the cursor is on the same screen as the window, check the
+ * region to paint for the cursor and remove it as necessary
+ */
+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
+
+ SCREEN_EPILOGUE (pScreen, PaintWindowBackground, rfbSpritePaintWindowBackground);
+}
+
+static void
+rfbSpritePaintWindowBorder (pWin, pRegion, what)
+ WindowPtr pWin;
+ RegionPtr pRegion;
+ int what;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, PaintWindowBorder);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pVNC->cursorIsDrawn)
+ {
+ /*
+ * If the cursor is on the same screen as the window, check the
+ * region to paint for the cursor and remove it as necessary
+ */
+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
+
+ SCREEN_EPILOGUE (pScreen, PaintWindowBorder, rfbSpritePaintWindowBorder);
+}
+
+static void
+rfbSpriteCopyWindow (pWin, ptOldOrg, pRegion)
+ WindowPtr pWin;
+ DDXPointRec ptOldOrg;
+ RegionPtr pRegion;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ BoxRec cursorBox;
+ int dx, dy;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, CopyWindow);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pVNC->cursorIsDrawn)
+ {
+ /*
+ * check both the source and the destination areas. The given
+ * region is source relative, so offset the cursor box by
+ * the delta position
+ */
+ cursorBox = pScreenPriv->saved;
+ dx = pWin->drawable.x - ptOldOrg.x;
+ dy = pWin->drawable.y - ptOldOrg.y;
+ cursorBox.x1 -= dx;
+ cursorBox.x2 -= dx;
+ cursorBox.y1 -= dy;
+ cursorBox.y2 -= dy;
+ if (RECT_IN_REGION( pScreen, pRegion, &pScreenPriv->saved) != rgnOUT ||
+ RECT_IN_REGION( pScreen, pRegion, &cursorBox) != rgnOUT)
+ rfbSpriteRemoveCursor (pScreen);
+ }
+
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pRegion);
+
+ SCREEN_EPILOGUE (pScreen, CopyWindow, rfbSpriteCopyWindow);
+}
+
+static void
+rfbSpriteClearToBackground (pWin, x, y, w, h, generateExposures)
+ WindowPtr pWin;
+ short x,y;
+ unsigned short w,h;
+ Bool generateExposures;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ rfbSpriteScreenPtr pScreenPriv;
+ int realw, realh;
+ VNCSCREENPTR(pScreen);
+
+ SCREEN_PROLOGUE (pScreen, ClearToBackground);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (GC_CHECK(pWin))
+ {
+ if (!(realw = w))
+ realw = (int) pWin->drawable.width - x;
+ if (!(realh = h))
+ realh = (int) pWin->drawable.height - y;
+ if (ORG_OVERLAP(&pScreenPriv->saved, pWin->drawable.x, pWin->drawable.y,
+ x, y, realw, realh))
+ {
+ rfbSpriteRemoveCursor (pScreen);
+ }
+ }
+
+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
+
+ SCREEN_EPILOGUE (pScreen, ClearToBackground, rfbSpriteClearToBackground);
+}
+
+/*
+ * GC Func wrappers
+ */
+
+static void
+rfbSpriteValidateGC (pGC, changes, pDrawable)
+ GCPtr pGC;
+ unsigned long changes;
+ DrawablePtr pDrawable;
+{
+ GC_FUNC_PROLOGUE (pGC);
+
+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
+
+ pGCPriv->wrapOps = NULL;
+ if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr) pDrawable)->viewable)
+ {
+ WindowPtr pWin;
+ RegionPtr pRegion;
+
+ pWin = (WindowPtr) pDrawable;
+ pRegion = &pWin->clipList;
+ if (pGC->subWindowMode == IncludeInferiors)
+ pRegion = &pWin->borderClip;
+ if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion))
+ pGCPriv->wrapOps = pGC->ops;
+ }
+
+ GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteChangeGC (pGC, mask)
+ GCPtr pGC;
+ unsigned long mask;
+{
+ GC_FUNC_PROLOGUE (pGC);
+
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+
+ GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteCopyGC (pGCSrc, mask, pGCDst)
+ GCPtr pGCSrc, pGCDst;
+ unsigned long mask;
+{
+ GC_FUNC_PROLOGUE (pGCDst);
+
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+
+ GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+rfbSpriteDestroyGC (pGC)
+ GCPtr pGC;
+{
+ GC_FUNC_PROLOGUE (pGC);
+
+ (*pGC->funcs->DestroyGC) (pGC);
+
+ GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteChangeClip (pGC, type, pvalue, nrects)
+ GCPtr pGC;
+ int type;
+ pointer pvalue;
+ int nrects;
+{
+ GC_FUNC_PROLOGUE (pGC);
+
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+
+ GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteCopyClip(pgcDst, pgcSrc)
+ GCPtr pgcDst, pgcSrc;
+{
+ GC_FUNC_PROLOGUE (pgcDst);
+
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+
+ GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+rfbSpriteDestroyClip(pGC)
+ GCPtr pGC;
+{
+ GC_FUNC_PROLOGUE (pGC);
+
+ (* pGC->funcs->DestroyClip)(pGC);
+
+ GC_FUNC_EPILOGUE (pGC);
+}
+
+/*
+ * GC Op wrappers
+ */
+
+static void
+rfbSpriteFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nInit; /* number of spans to fill */
+ DDXPointPtr pptInit; /* pointer to list of start points */
+ int *pwidthInit; /* pointer to list of n widths */
+ int fSorted;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ register DDXPointPtr pts;
+ register int *widths;
+ register int nPts;
+
+ for (pts = pptInit, widths = pwidthInit, nPts = nInit;
+ nPts--;
+ pts++, widths++)
+ {
+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ char *psrc;
+ register DDXPointPtr ppt;
+ int *pwidth;
+ int nspans;
+ int fSorted;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ register DDXPointPtr pts;
+ register int *widths;
+ register int nPts;
+
+ for (pts = ppt, widths = pwidth, nPts = nspans;
+ nPts--;
+ pts++, widths++)
+ {
+ if (SPN_OVERLAP(&pScreenPriv->saved,pts->y,pts->x,*widths))
+ {
+ rfbSpriteRemoveCursor(pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int depth;
+ int x;
+ int y;
+ int w;
+ int h;
+ int format;
+ char *pBits;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ if (ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,
+ x,y,w,h))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static RegionPtr
+rfbSpriteCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
+ DrawablePtr pSrc;
+ DrawablePtr pDst;
+ GCPtr pGC;
+ int srcx;
+ int srcy;
+ int w;
+ int h;
+ int dstx;
+ int dsty;
+{
+ RegionPtr rgn;
+ VNCSCREENPTR(pGC->pScreen);
+
+ GC_SETUP(pDst, pGC);
+
+ /* check destination/source overlap. */
+ if (GC_CHECK((WindowPtr) pDst) &&
+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
+ ((pDst == pSrc) &&
+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
+ {
+ rfbSpriteRemoveCursor (pDst->pScreen);
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty);
+
+ GC_OP_EPILOGUE (pGC);
+
+ return rgn;
+}
+
+static RegionPtr
+rfbSpriteCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
+ DrawablePtr pSrc;
+ DrawablePtr pDst;
+ register GCPtr pGC;
+ int srcx,
+ srcy;
+ int w,
+ h;
+ int dstx,
+ dsty;
+ unsigned long plane;
+{
+ RegionPtr rgn;
+ VNCSCREENPTR(pGC->pScreen);
+
+ GC_SETUP(pDst, pGC);
+
+ /*
+ * check destination/source for overlap.
+ */
+ if (GC_CHECK((WindowPtr) pDst) &&
+ (ORG_OVERLAP(&pScreenPriv->saved,pDst->x,pDst->y,dstx,dsty,w,h) ||
+ ((pDst == pSrc) &&
+ ORG_OVERLAP(&pScreenPriv->saved,pSrc->x,pSrc->y,srcx,srcy,w,h))))
+ {
+ rfbSpriteRemoveCursor (pDst->pScreen);
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+
+ GC_OP_EPILOGUE (pGC);
+
+ return rgn;
+}
+
+static void
+rfbSpritePolyPoint (pDrawable, pGC, mode, npt, pptInit)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int mode; /* Origin or Previous */
+ int npt;
+ xPoint *pptInit;
+{
+ xPoint t;
+ int n;
+ BoxRec cursor;
+ register xPoint *pts;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ if (npt && GC_CHECK((WindowPtr) pDrawable))
+ {
+ cursor.x1 = pScreenPriv->saved.x1 - pDrawable->x;
+ cursor.y1 = pScreenPriv->saved.y1 - pDrawable->y;
+ cursor.x2 = pScreenPriv->saved.x2 - pDrawable->x;
+ cursor.y2 = pScreenPriv->saved.y2 - pDrawable->y;
+
+ if (mode == CoordModePrevious)
+ {
+ t.x = 0;
+ t.y = 0;
+ for (pts = pptInit, n = npt; n--; pts++)
+ {
+ t.x += pts->x;
+ t.y += pts->y;
+ if (cursor.x1 <= t.x && t.x <= cursor.x2 &&
+ cursor.y1 <= t.y && t.y <= cursor.y2)
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (pts = pptInit, n = npt; n--; pts++)
+ {
+ if (cursor.x1 <= pts->x && pts->x <= cursor.x2 &&
+ cursor.y1 <= pts->y && pts->y <= cursor.y2)
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pptInit);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolylines (pDrawable, pGC, mode, npt, pptInit)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int mode;
+ int npt;
+ DDXPointPtr pptInit;
+{
+ BoxPtr cursor;
+ register DDXPointPtr pts;
+ int n;
+ int x, y, x1, y1, x2, y2;
+ int lw;
+ int extra;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ if (npt && GC_CHECK((WindowPtr) pDrawable))
+ {
+ cursor = &pScreenPriv->saved;
+ lw = pGC->lineWidth;
+ x = pptInit->x + pDrawable->x;
+ y = pptInit->y + pDrawable->y;
+
+ if (npt == 1)
+ {
+ extra = lw >> 1;
+ if (LINE_OVERLAP(cursor, x, y, x, y, extra))
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ }
+ else
+ {
+ extra = lw >> 1;
+ /*
+ * mitered joins can project quite a way from
+ * the line end; the 11 degree miter limit limits
+ * this extension to 10.43 * lw / 2, rounded up
+ * and converted to int yields 6 * lw
+ */
+ if (pGC->joinStyle == JoinMiter)
+ extra = 6 * lw;
+ else if (pGC->capStyle == CapProjecting)
+ extra = lw;
+ for (pts = pptInit + 1, n = npt - 1; n--; pts++)
+ {
+ x1 = x;
+ y1 = y;
+ if (mode == CoordModeOrigin)
+ {
+ x2 = pDrawable->x + pts->x;
+ y2 = pDrawable->y + pts->y;
+ }
+ else
+ {
+ x2 = x + pts->x;
+ y2 = y + pts->y;
+ }
+ x = x2;
+ y = y2;
+ LINE_SORT(x1, y1, x2, y2);
+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+ }
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, pptInit);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolySegment(pDrawable, pGC, nseg, pSegs)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nseg;
+ xSegment *pSegs;
+{
+ int n;
+ register xSegment *segs;
+ BoxPtr cursor;
+ int x1, y1, x2, y2;
+ int extra;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (nseg && GC_CHECK((WindowPtr) pDrawable))
+ {
+ cursor = &pScreenPriv->saved;
+ extra = pGC->lineWidth >> 1;
+ if (pGC->capStyle == CapProjecting)
+ extra = pGC->lineWidth;
+ for (segs = pSegs, n = nseg; n--; segs++)
+ {
+ x1 = segs->x1 + pDrawable->x;
+ y1 = segs->y1 + pDrawable->y;
+ x2 = segs->x2 + pDrawable->x;
+ y2 = segs->y2 + pDrawable->y;
+ LINE_SORT(x1, y1, x2, y2);
+ if (LINE_OVERLAP(cursor, x1, y1, x2, y2, extra))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, pSegs);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolyRectangle(pDrawable, pGC, nrects, pRects)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nrects;
+ xRectangle *pRects;
+{
+ register xRectangle *rects;
+ BoxPtr cursor;
+ int lw;
+ int n;
+ int x1, y1, x2, y2;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ lw = pGC->lineWidth >> 1;
+ cursor = &pScreenPriv->saved;
+ for (rects = pRects, n = nrects; n--; rects++)
+ {
+ x1 = rects->x + pDrawable->x;
+ y1 = rects->y + pDrawable->y;
+ x2 = x1 + (int)rects->width;
+ y2 = y1 + (int)rects->height;
+ if (LINE_OVERLAP(cursor, x1, y1, x2, y1, lw) ||
+ LINE_OVERLAP(cursor, x2, y1, x2, y2, lw) ||
+ LINE_OVERLAP(cursor, x1, y2, x2, y2, lw) ||
+ LINE_OVERLAP(cursor, x1, y1, x1, y2, lw))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, pRects);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolyArc(pDrawable, pGC, narcs, parcs)
+ DrawablePtr pDrawable;
+ register GCPtr pGC;
+ int narcs;
+ xArc *parcs;
+{
+ BoxPtr cursor;
+ int lw;
+ int n;
+ register xArc *arcs;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ lw = pGC->lineWidth >> 1;
+ cursor = &pScreenPriv->saved;
+ for (arcs = parcs, n = narcs; n--; arcs++)
+ {
+ if (ORG_OVERLAP (cursor, pDrawable->x, pDrawable->y,
+ arcs->x - lw, arcs->y - lw,
+ (int) arcs->width + pGC->lineWidth,
+ (int) arcs->height + pGC->lineWidth))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, parcs);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteFillPolygon(pDrawable, pGC, shape, mode, count, pPts)
+ register DrawablePtr pDrawable;
+ register GCPtr pGC;
+ int shape, mode;
+ int count;
+ DDXPointPtr pPts;
+{
+ int x, y, minx, miny, maxx, maxy;
+ register DDXPointPtr pts;
+ int n;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ if (count && GC_CHECK((WindowPtr) pDrawable))
+ {
+ x = pDrawable->x;
+ y = pDrawable->y;
+ pts = pPts;
+ minx = maxx = pts->x;
+ miny = maxy = pts->y;
+ pts++;
+ n = count - 1;
+
+ if (mode == CoordModeOrigin)
+ {
+ for (; n--; pts++)
+ {
+ if (pts->x < minx)
+ minx = pts->x;
+ else if (pts->x > maxx)
+ maxx = pts->x;
+ if (pts->y < miny)
+ miny = pts->y;
+ else if (pts->y > maxy)
+ maxy = pts->y;
+ }
+ minx += x;
+ miny += y;
+ maxx += x;
+ maxy += y;
+ }
+ else
+ {
+ x += minx;
+ y += miny;
+ minx = maxx = x;
+ miny = maxy = y;
+ for (; n--; pts++)
+ {
+ x += pts->x;
+ y += pts->y;
+ if (x < minx)
+ minx = x;
+ else if (x > maxx)
+ maxx = x;
+ if (y < miny)
+ miny = y;
+ else if (y > maxy)
+ maxy = y;
+ }
+ }
+ if (BOX_OVERLAP(&pScreenPriv->saved,minx,miny,maxx,maxy))
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pPts);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolyFillRect(pDrawable, pGC, nrectFill, prectInit)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int nrectFill; /* number of rectangles to fill */
+ xRectangle *prectInit; /* Pointer to first rectangle to fill */
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ register int nRect;
+ register xRectangle *pRect;
+ register int xorg, yorg;
+
+ xorg = pDrawable->x;
+ yorg = pDrawable->y;
+
+ for (nRect = nrectFill, pRect = prectInit; nRect--; pRect++) {
+ if (ORGRECT_OVERLAP(&pScreenPriv->saved,xorg,yorg,pRect)){
+ rfbSpriteRemoveCursor(pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrectFill, prectInit);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolyFillArc(pDrawable, pGC, narcs, parcs)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int narcs;
+ xArc *parcs;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ {
+ register int n;
+ BoxPtr cursor;
+ register xArc *arcs;
+
+ cursor = &pScreenPriv->saved;
+
+ for (arcs = parcs, n = narcs; n--; arcs++)
+ {
+ if (ORG_OVERLAP(cursor, pDrawable->x, pDrawable->y,
+ arcs->x, arcs->y,
+ (int) arcs->width, (int) arcs->height))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ break;
+ }
+ }
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, parcs);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+/*
+ * general Poly/Image text function. Extract glyph information,
+ * compute bounding box and remove cursor if it is overlapped.
+ */
+
+static Bool
+rfbSpriteTextOverlap (DrawablePtr pDraw, FontPtr font, int x, int y, unsigned int n, CharInfoPtr *charinfo, Bool imageblt, unsigned int w, BoxPtr cursorBox)
+{
+ ExtentInfoRec extents;
+
+ x += pDraw->x;
+ y += pDraw->y;
+
+ if (FONTMINBOUNDS(font,characterWidth) >= 0)
+ {
+ /* compute an approximate (but covering) bounding box */
+ if (!imageblt || (charinfo[0]->metrics.leftSideBearing < 0))
+ extents.overallLeft = charinfo[0]->metrics.leftSideBearing;
+ else
+ extents.overallLeft = 0;
+ if (w)
+ extents.overallRight = w - charinfo[n-1]->metrics.characterWidth;
+ else
+ extents.overallRight = FONTMAXBOUNDS(font,characterWidth)
+ * (n - 1);
+ if (imageblt && (charinfo[n-1]->metrics.characterWidth >
+ charinfo[n-1]->metrics.rightSideBearing))
+ extents.overallRight += charinfo[n-1]->metrics.characterWidth;
+ else
+ extents.overallRight += charinfo[n-1]->metrics.rightSideBearing;
+ if (imageblt && FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
+ extents.overallAscent = FONTASCENT(font);
+ else
+ extents.overallAscent = FONTMAXBOUNDS(font, ascent);
+ if (imageblt && FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
+ extents.overallDescent = FONTDESCENT(font);
+ else
+ extents.overallDescent = FONTMAXBOUNDS(font,descent);
+ if (!BOX_OVERLAP(cursorBox,
+ x + extents.overallLeft,
+ y - extents.overallAscent,
+ x + extents.overallRight,
+ y + extents.overallDescent))
+ return FALSE;
+ else if (imageblt && w)
+ return TRUE;
+ /* if it does overlap, fall through and compute exactly, because
+ * taking down the cursor is expensive enough to make this worth it
+ */
+ }
+ QueryGlyphExtents(font, charinfo, n, &extents);
+ if (imageblt)
+ {
+ if (extents.overallWidth > extents.overallRight)
+ extents.overallRight = extents.overallWidth;
+ if (extents.overallWidth < extents.overallLeft)
+ extents.overallLeft = extents.overallWidth;
+ if (extents.overallLeft > 0)
+ extents.overallLeft = 0;
+ if (extents.fontAscent > extents.overallAscent)
+ extents.overallAscent = extents.fontAscent;
+ if (extents.fontDescent > extents.overallDescent)
+ extents.overallDescent = extents.fontDescent;
+ }
+ return (BOX_OVERLAP(cursorBox,
+ x + extents.overallLeft,
+ y - extents.overallAscent,
+ x + extents.overallRight,
+ y + extents.overallDescent));
+}
+
+/*
+ * values for textType:
+ */
+#define TT_POLY8 0
+#define TT_IMAGE8 1
+#define TT_POLY16 2
+#define TT_IMAGE16 3
+
+static int
+rfbSpriteText (DrawablePtr pDraw, GCPtr pGC, int x, int y, unsigned long count, char *chars, FontEncoding fontEncoding, Bool textType, BoxPtr cursorBox)
+{
+ CharInfoPtr *charinfo;
+ register CharInfoPtr *info;
+ unsigned long i;
+ unsigned int n;
+ int w;
+ void (*drawFunc)() = NULL;
+
+ Bool imageblt;
+
+ imageblt = (textType == TT_IMAGE8) || (textType == TT_IMAGE16);
+
+ charinfo = (CharInfoPtr *) xalloc(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) {
+ if (rfbSpriteTextOverlap(pDraw, pGC->font, x, y, n, charinfo, imageblt, w, cursorBox))
+ rfbSpriteRemoveCursor(pDraw->pScreen);
+
+#ifdef AVOID_GLYPHBLT
+ /*
+ * On displays like Apollos, which do not optimize the GlyphBlt functions because they
+ * convert fonts to their internal form in RealizeFont and optimize text directly, we
+ * want to invoke the text functions here, not the GlyphBlt functions.
+ */
+ switch (textType)
+ {
+ case TT_POLY8:
+ drawFunc = (void (*)())pGC->ops->PolyText8;
+ break;
+ case TT_IMAGE8:
+ drawFunc = pGC->ops->ImageText8;
+ break;
+ case TT_POLY16:
+ drawFunc = (void (*)())pGC->ops->PolyText16;
+ break;
+ case TT_IMAGE16:
+ drawFunc = pGC->ops->ImageText16;
+ break;
+ }
+ (*drawFunc) (pDraw, pGC, x, y, (int) count, chars);
+#else /* don't AVOID_GLYPHBLT */
+ /*
+ * On the other hand, if the device does use GlyphBlt ultimately to do text, we
+ * don't want to slow it down by invoking the text functions and having them call
+ * GetGlyphs all over again, so we go directly to the GlyphBlt functions here.
+ */
+ drawFunc = imageblt ? pGC->ops->ImageGlyphBlt : pGC->ops->PolyGlyphBlt;
+ (*drawFunc) (pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
+#endif /* AVOID_GLYPHBLT */
+ }
+ xfree(charinfo);
+ return x + w;
+}
+
+static int
+rfbSpritePolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, char *chars)
+{
+ int ret;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count, chars,
+ Linear8Bit, TT_POLY8, &pScreenPriv->saved);
+ else
+ ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+ GC_OP_EPILOGUE (pGC);
+ return ret;
+}
+
+static int
+rfbSpritePolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, int count, unsigned short *chars)
+{
+ int ret;
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ ret = rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
+ (char *)chars,
+ FONTLASTROW(pGC->font) == 0 ?
+ Linear16Bit : TwoD16Bit, TT_POLY16, &pScreenPriv->saved);
+ else
+ ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+ GC_OP_EPILOGUE (pGC);
+ return ret;
+}
+
+static void
+rfbSpriteImageText8(pDrawable, pGC, x, y, count, chars)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int x, y;
+ int count;
+ char *chars;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
+ chars, Linear8Bit, TT_IMAGE8, &pScreenPriv->saved);
+ else
+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteImageText16(pDrawable, pGC, x, y, count, chars)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int x, y;
+ int count;
+ unsigned short *chars;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable))
+ (void) rfbSpriteText (pDrawable, pGC, x, y, (unsigned long)count,
+ (char *)chars,
+ FONTLASTROW(pGC->font) == 0 ?
+ Linear16Bit : TwoD16Bit, TT_IMAGE16, &pScreenPriv->saved);
+ else
+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpriteImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int x, y;
+ unsigned int nglyph;
+ CharInfoPtr *ppci; /* array of character info */
+ pointer pglyphBase; /* start of array of glyphs */
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP(pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable) &&
+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, TRUE, 0, &pScreenPriv->saved))
+ {
+ rfbSpriteRemoveCursor(pDrawable->pScreen);
+ }
+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ int x, y;
+ unsigned int nglyph;
+ CharInfoPtr *ppci; /* array of character info */
+ pointer pglyphBase; /* start of array of glyphs */
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+
+ GC_SETUP (pDrawable, pGC);
+
+ GC_OP_PROLOGUE (pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable) &&
+ rfbSpriteTextOverlap (pDrawable, pGC->font, x, y, nglyph, ppci, FALSE, 0, &pScreenPriv->saved))
+ {
+ rfbSpriteRemoveCursor(pDrawable->pScreen);
+ }
+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+static void
+rfbSpritePushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
+ GCPtr pGC;
+ PixmapPtr pBitMap;
+ DrawablePtr pDrawable;
+ int w, h, x, y;
+{
+ VNCSCREENPTR(pDrawable->pScreen);
+ GC_SETUP(pDrawable, pGC);
+
+ if (GC_CHECK((WindowPtr) pDrawable) &&
+ ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y,x,y,w,h))
+ {
+ rfbSpriteRemoveCursor (pDrawable->pScreen);
+ }
+
+ GC_OP_PROLOGUE (pGC);
+
+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
+
+ GC_OP_EPILOGUE (pGC);
+}
+
+#ifdef NEED_LINEHELPER
+/*
+ * I don't expect this routine will ever be called, as the GC
+ * will have been unwrapped for the line drawing
+ */
+
+static void
+rfbSpriteLineHelper()
+{
+ FatalError("rfbSpriteLineHelper called\n");
+}
+#endif
+
+/*
+ * miPointer interface routines
+ */
+
+#define SPRITE_PAD 8
+
+static Bool
+rfbSpriteRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (pCursor == pScreenPriv->pCursor)
+ pScreenPriv->checkPixels = TRUE;
+ return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
+}
+
+static Bool
+rfbSpriteUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
+}
+
+static void
+rfbSpriteSetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+ rfbSpriteScreenPtr pScreenPriv;
+ rfbClientPtr cl, nextCl;
+ VNCSCREENPTR(pScreen);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ if (!pCursor)
+ {
+ pScreenPriv->shouldBeUp = FALSE;
+ if (pVNC->cursorIsDrawn)
+ rfbSpriteRemoveCursor (pScreen);
+ pScreenPriv->pCursor = 0;
+ return;
+ }
+ pScreenPriv->shouldBeUp = TRUE;
+ if (pScreenPriv->x == x &&
+ pScreenPriv->y == y &&
+ pScreenPriv->pCursor == pCursor &&
+ !pScreenPriv->checkPixels)
+ {
+ return;
+ }
+ pScreenPriv->x = x;
+ pScreenPriv->y = y;
+ pScreenPriv->pCacheWin = NullWindow;
+ if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
+ {
+ pScreenPriv->pCursor = pCursor;
+ rfbSpriteFindColors (pScreen);
+ }
+ if (pVNC->cursorIsDrawn) {
+ int sx, sy;
+ /*
+ * check to see if the old saved region
+ * encloses the new sprite, in which case we use
+ * the flicker-free MoveCursor primitive.
+ */
+ sx = pScreenPriv->x - (int)pCursor->bits->xhot;
+ sy = pScreenPriv->y - (int)pCursor->bits->yhot;
+ if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
+ sx < pScreenPriv->saved.x2 &&
+ sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
+ sy < pScreenPriv->saved.y2 &&
+ (int) pCursor->bits->width + (2 * SPRITE_PAD) ==
+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
+ (int) pCursor->bits->height + (2 * SPRITE_PAD) ==
+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1
+ )
+ {
+ pVNC->cursorIsDrawn = FALSE;
+ if (!(sx >= pScreenPriv->saved.x1 &&
+ sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
+ sy >= pScreenPriv->saved.y1 &&
+ sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
+ {
+ int oldx1, oldy1, dx, dy;
+
+ oldx1 = pScreenPriv->saved.x1;
+ oldy1 = pScreenPriv->saved.y1;
+ dx = oldx1 - (sx - SPRITE_PAD);
+ dy = oldy1 - (sy - SPRITE_PAD);
+ pScreenPriv->saved.x1 -= dx;
+ pScreenPriv->saved.y1 -= dy;
+ pScreenPriv->saved.x2 -= dx;
+ pScreenPriv->saved.y2 -= dy;
+ (void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
+ pScreenPriv->saved.x1,
+ pScreenPriv->saved.y1,
+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
+ dx, dy);
+ }
+ (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
+ pScreenPriv->saved.x1,
+ pScreenPriv->saved.y1,
+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
+ sx - pScreenPriv->saved.x1,
+ sy - pScreenPriv->saved.y1,
+ pScreenPriv->colors[SOURCE_COLOR].pixel,
+ pScreenPriv->colors[MASK_COLOR].pixel);
+ pVNC->cursorIsDrawn = TRUE;
+ }
+ else
+ {
+ rfbSpriteRemoveCursor (pScreen);
+ }
+ }
+#if 0
+ if (!pVNC->cursorIsDrawn && pScreenPriv->pCursor)
+ rfbSpriteRestoreCursor (pScreen);
+#endif
+ if (pVNC->cursorIsDrawn)
+ rfbSpriteRemoveCursor (pScreen);
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ if (cl->enableCursorPosUpdates) {
+ if (x == cl->cursorX && y == cl->cursorY) {
+ cl->cursorWasMoved = FALSE;
+ continue;
+ }
+ cl->cursorWasMoved = TRUE;
+ }
+ if (REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) {
+ /* cursorIsDrawn is guaranteed to be FALSE here, so we definitely
+ want to send a screen update to the client, even if that's only
+ putting up the cursor */
+ rfbSendFramebufferUpdate(pScreen, cl);
+ }
+ }
+}
+
+static void
+rfbSpriteMoveCursor (ScreenPtr pScreen, int x, int y)
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ rfbSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
+}
+
+/*
+ * undraw/draw cursor
+ */
+
+void
+rfbSpriteRemoveCursor (pScreen)
+ ScreenPtr pScreen;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+ VNCSCREENPTR(pScreen);
+
+ if (!pVNC->cursorIsDrawn)
+ return;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ pVNC->dontSendFramebufferUpdate = TRUE;
+ pVNC->cursorIsDrawn = FALSE;
+ pScreenPriv->pCacheWin = NullWindow;
+ if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
+ pScreenPriv->saved.x1,
+ pScreenPriv->saved.y1,
+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
+ {
+ pVNC->cursorIsDrawn = TRUE;
+ }
+ pVNC->dontSendFramebufferUpdate = FALSE;
+}
+
+
+void
+rfbSpriteRestoreCursor (pScreen)
+ ScreenPtr pScreen;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+ int x, y;
+ CursorPtr pCursor;
+ VNCSCREENPTR(pScreen);
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ pCursor = pScreenPriv->pCursor;
+
+ if (pVNC->cursorIsDrawn || !pCursor)
+ return;
+
+ pVNC->dontSendFramebufferUpdate = TRUE;
+
+ rfbSpriteComputeSaved (pScreen);
+
+ x = pScreenPriv->x - (int)pCursor->bits->xhot;
+ y = pScreenPriv->y - (int)pCursor->bits->yhot;
+ if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
+ pScreenPriv->saved.x1,
+ pScreenPriv->saved.y1,
+ pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
+ pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
+ {
+ if (pScreenPriv->checkPixels)
+ rfbSpriteFindColors (pScreen);
+ if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
+ pScreenPriv->colors[SOURCE_COLOR].pixel,
+ pScreenPriv->colors[MASK_COLOR].pixel))
+ pVNC->cursorIsDrawn = TRUE;
+ }
+
+ pVNC->dontSendFramebufferUpdate = FALSE;
+}
+
+/*
+ * compute the desired area of the screen to save
+ */
+
+static void
+rfbSpriteComputeSaved (pScreen)
+ ScreenPtr pScreen;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+ int x, y, w, h;
+ int wpad, hpad;
+ CursorPtr pCursor;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ pCursor = pScreenPriv->pCursor;
+ x = pScreenPriv->x - (int)pCursor->bits->xhot;
+ y = pScreenPriv->y - (int)pCursor->bits->yhot;
+ w = pCursor->bits->width;
+ h = pCursor->bits->height;
+ wpad = SPRITE_PAD;
+ hpad = SPRITE_PAD;
+ pScreenPriv->saved.x1 = x - wpad;
+ pScreenPriv->saved.y1 = y - hpad;
+ pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
+ pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
+}
+
+
+/*
+ * this function is called when the cursor shape is being changed
+ */
+
+static Bool
+rfbDisplayCursor(pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ rfbClientPtr cl;
+ rfbSpriteScreenPtr pPriv;
+ Bool status;
+
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (cl->enableCursorShapeUpdates)
+ cl->cursorWasChanged = TRUE;
+ }
+
+ pPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+ status = (*pPriv->DisplayCursor)(pScreen, pCursor);
+
+ /* send new cursor shape to interested viewers */
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (cl->cursorWasChanged) {
+ rfbSendFramebufferUpdate(pScreen, cl);
+ }
+ }
+
+ return status;
+}
+
+
+/*
+ * obtain current cursor pointer
+ */
+
+CursorPtr
+rfbSpriteGetCursorPtr (pScreen)
+ ScreenPtr pScreen;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ return pScreenPriv->pCursor;
+}
+
+/*
+ * obtain current cursor position
+ */
+
+void
+rfbSpriteGetCursorPos (pScreen, px, py)
+ ScreenPtr pScreen;
+ int *px, *py;
+{
+ rfbSpriteScreenPtr pScreenPriv;
+
+ pScreenPriv = (rfbSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
+ rfbSpriteScreenKey);
+
+ *px = pScreenPriv->x;
+ *py = pScreenPriv->y;
+}
+
--- xorg-server-1.7.4/hw/vnc/sprite.h
+++ xorg-server-1.7.4/hw/vnc/sprite.h
@@ -0,0 +1,141 @@
+/*
+ * sprite.h
+ *
+ * software-sprite/sprite drawing - based on misprite
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1989 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.
+*/
+
+typedef struct {
+ Bool (*RealizeCursor)(
+ ScreenPtr /*pScreen*/,
+ CursorPtr /*pCursor*/
+);
+ Bool (*UnrealizeCursor)(
+ ScreenPtr /*pScreen*/,
+ CursorPtr /*pCursor*/
+);
+ Bool (*PutUpCursor)(
+ ScreenPtr /*pScreen*/,
+ CursorPtr /*pCursor*/,
+ int /*x*/,
+ int /*y*/,
+ unsigned long /*source*/,
+ unsigned long /*mask*/
+);
+ Bool (*SaveUnderCursor)(
+ ScreenPtr /*pScreen*/,
+ int /*x*/,
+ int /*y*/,
+ int /*w*/,
+ int /*h*/
+);
+ Bool (*RestoreUnderCursor)(
+ ScreenPtr /*pScreen*/,
+ int /*x*/,
+ int /*y*/,
+ int /*w*/,
+ int /*h*/
+);
+ Bool (*MoveCursor)(
+ ScreenPtr /*pScreen*/,
+ CursorPtr /*pCursor*/,
+ int /*x*/,
+ int /*y*/,
+ int /*w*/,
+ int /*h*/,
+ int /*dx*/,
+ int /*dy*/,
+ unsigned long /*source*/,
+ unsigned long /*mask*/
+);
+ Bool (*ChangeSave)(
+ ScreenPtr /*pScreen*/,
+ int /*x*/,
+ int /*y*/,
+ int /*w*/,
+ int /*h*/,
+ int /*dx*/,
+ int /*dy*/
+);
+
+} rfbSpriteCursorFuncRec, *rfbSpriteCursorFuncPtr;
+
+extern Bool rfbSpriteInitialize(
+#if NeedFunctionPrototypes
+ ScreenPtr /*pScreen*/,
+ rfbSpriteCursorFuncPtr /*cursorFuncs*/,
+ miPointerScreenFuncPtr /*screenFuncs*/
+#endif
+);
+
+extern void rfbSpriteRestoreCursor(
+#if NeedFunctionPrototypes
+ ScreenPtr /*pScreen*/
+#endif
+);
+
+extern void rfbSpriteRemoveCursor(
+#if NeedFunctionPrototypes
+ ScreenPtr /*pScreen*/
+#endif
+);
+
+extern CursorPtr rfbSpriteGetCursorPtr(
+#if NeedFunctionPrototypes
+ ScreenPtr /*pScreen*/
+#endif
+);
+
+extern void rfbSpriteGetCursorPos(
+#if NeedFunctionPrototypes
+ ScreenPtr /*pScreen*/,
+ int * /*px*/,
+ int * /*py*/
+#endif
+);
--- xorg-server-1.7.4/hw/vnc/spritest.h
+++ xorg-server-1.7.4/hw/vnc/spritest.h
@@ -0,0 +1,138 @@
+/*
+ * spritest.h
+ *
+ * sprite structures - based on misprite
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+
+Copyright (c) 1989 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.
+*/
+
+# include "sprite.h"
+
+#ifdef RENDER
+# include "picturestr.h"
+#endif
+
+/*
+ * per screen information
+ */
+
+typedef struct {
+ CloseScreenProcPtr CloseScreen;
+ GetImageProcPtr GetImage;
+ GetSpansProcPtr GetSpans;
+ SourceValidateProcPtr SourceValidate;
+ CreateGCProcPtr CreateGC;
+ ScreenBlockHandlerProcPtr BlockHandler;
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ SaveDoomedAreasProcPtr SaveDoomedAreas;
+ RestoreAreasProcPtr RestoreAreas;
+ DisplayCursorProcPtr DisplayCursor;
+#ifdef RENDER
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+#endif
+
+ CursorPtr pCursor;
+ int x;
+ int y;
+ Bool shouldBeUp;
+ BoxRec saved;
+ WindowPtr pCacheWin;
+ Bool isInCacheWin;
+ Bool checkPixels;
+ xColorItem colors[2];
+ ColormapPtr pInstalledMap;
+ ColormapPtr pColormap;
+ VisualPtr pVisual;
+ rfbSpriteCursorFuncPtr funcs;
+} rfbSpriteScreenRec, *rfbSpriteScreenPtr;
+
+#define SOURCE_COLOR 0
+#define MASK_COLOR 1
+
+typedef struct {
+ GCFuncs *wrapFuncs;
+ GCOps *wrapOps;
+} rfbSpriteGCRec, *rfbSpriteGCPtr;
+
+/*
+ * Overlap BoxPtr and Box elements
+ */
+#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
+ (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
+ ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
+
+/*
+ * Overlap BoxPtr, origins, and rectangle
+ */
+#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
+ BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
+
+/*
+ * Overlap BoxPtr, origins and RectPtr
+ */
+#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
+ ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
+ (int)((pRect)->width), (int)((pRect)->height))
+/*
+ * Overlap BoxPtr and horizontal span
+ */
+#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
+
+#define LINE_SORT(x1,y1,x2,y2) \
+{ int _t; \
+ if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
+ if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
+
+#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
+ BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
--- xorg-server-1.7.4/hw/vnc/stats.c
+++ xorg-server-1.7.4/hw/vnc/stats.c
@@ -0,0 +1,117 @@
+/*
+ * stats.c
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "rfb.h"
+
+static char* encNames[] = {
+ "raw", "copyRect", "RRE", "[encoding 3]", "CoRRE", "hextile",
+ "zlib", "tight", "[encoding 8]", "[encoding 9]"
+};
+
+
+void
+rfbResetStats(rfbClientPtr cl)
+{
+ int i;
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ cl->rfbBytesSent[i] = 0;
+ cl->rfbRectanglesSent[i] = 0;
+ }
+ cl->rfbLastRectMarkersSent = 0;
+ cl->rfbLastRectBytesSent = 0;
+ cl->rfbCursorShapeBytesSent = 0;
+ cl->rfbCursorShapeUpdatesSent = 0;
+ cl->rfbCursorPosBytesSent = 0;
+ cl->rfbCursorPosUpdatesSent = 0;
+ cl->rfbFramebufferUpdateMessagesSent = 0;
+ cl->rfbRawBytesEquivalent = 0;
+ cl->rfbKeyEventsRcvd = 0;
+ cl->rfbPointerEventsRcvd = 0;
+}
+
+void
+rfbPrintStats(rfbClientPtr cl)
+{
+ int i;
+ int totalRectanglesSent = 0;
+ int totalBytesSent = 0;
+
+ rfbLog("Statistics:\n");
+
+ if ((cl->rfbKeyEventsRcvd != 0) || (cl->rfbPointerEventsRcvd != 0))
+ rfbLog(" key events received %d, pointer events %d\n",
+ cl->rfbKeyEventsRcvd, cl->rfbPointerEventsRcvd);
+
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ totalRectanglesSent += cl->rfbRectanglesSent[i];
+ totalBytesSent += cl->rfbBytesSent[i];
+ }
+ totalRectanglesSent += (cl->rfbCursorShapeUpdatesSent +
+ cl->rfbCursorPosUpdatesSent +
+ cl->rfbLastRectMarkersSent);
+ totalBytesSent += (cl->rfbCursorShapeBytesSent +
+ cl->rfbCursorPosBytesSent +
+ cl->rfbLastRectBytesSent);
+
+ rfbLog(" framebuffer updates %d, rectangles %d, bytes %d\n",
+ cl->rfbFramebufferUpdateMessagesSent, totalRectanglesSent,
+ totalBytesSent);
+
+ if (cl->rfbLastRectMarkersSent != 0)
+ rfbLog(" LastRect markers %d, bytes %d\n",
+ cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent);
+
+ if (cl->rfbCursorShapeUpdatesSent != 0)
+ rfbLog(" cursor shape updates %d, bytes %d\n",
+ cl->rfbCursorShapeUpdatesSent, cl->rfbCursorShapeBytesSent);
+
+ if (cl->rfbCursorPosUpdatesSent != 0)
+ rfbLog(" cursor position updates %d, bytes %d\n",
+ cl->rfbCursorPosUpdatesSent, cl->rfbCursorPosBytesSent);
+
+ for (i = 0; i < MAX_ENCODINGS; i++) {
+ if (cl->rfbRectanglesSent[i] != 0)
+ rfbLog(" %s rectangles %d, bytes %d\n",
+ encNames[i], cl->rfbRectanglesSent[i], cl->rfbBytesSent[i]);
+ }
+
+ if ((totalBytesSent - cl->rfbBytesSent[rfbEncodingCopyRect]) != 0) {
+ rfbLog(" raw bytes equivalent %d, compression ratio %f\n",
+ cl->rfbRawBytesEquivalent,
+ (double)cl->rfbRawBytesEquivalent
+ / (double)(totalBytesSent -
+ cl->rfbBytesSent[rfbEncodingCopyRect] -
+ cl->rfbCursorShapeBytesSent -
+ cl->rfbCursorPosBytesSent -
+ cl->rfbLastRectBytesSent));
+ }
+}
--- xorg-server-1.7.4/hw/vnc/symlink-vnc.sh
+++ xorg-server-1.7.4/hw/vnc/symlink-vnc.sh
@@ -0,0 +1,198 @@
+#!/bin/sh
+
+#
+# A script that symlinks source files from vnc to modular
+#
+# Author: Soren Sandmann (sandmann@redhat.com) (original)
+# adapted for vnc by Alan Hourihane <alanh@fairlite.demon.co.uk>
+
+#
+# Things we would like to do
+#
+# - Check that all the relevant files exist
+# - AUTHORS, autogen.sh, configure.ac, ...
+# - Check that we have actually linked everything
+# - if a file doesn't need to be linked, then it needs
+# to be listed as "not-linked"
+# - Compute diffs between all the files (shouldn't be necessary)
+# - possibly check that files are listet in Makefile.am's
+# - Clean target directory of irrelevant files
+#
+
+check_destinations () {
+ # don't do anything - we are relying on the side
+ # effect of dst_dir
+ true
+}
+
+check_exist() {
+ # Check whether $1 exists
+
+ if [ ! -e $1 ] ; then
+ error "$1 not found"
+ fi
+}
+
+delete_existing() {
+ # Delete $2
+
+ rm -f $2
+}
+
+link_files() {
+ # Link $1 to $2
+
+ if [ ! -e $2 ] ; then
+ ln -s $1 $2
+ fi
+}
+
+main() {
+ check_args $1 $2
+
+ run check_destinations "Creating destination directories"
+ run check_exist "Checking that the source files exist"
+ run delete_existing "Deleting existing files"
+ run link_files "Linking files"
+}
+
+## actual symlinking
+
+symlink_vnc() {
+ src_dir .
+ dst_dir .
+ action d3des.c
+ action d3des.h
+ action auth.c
+ action cmap.c
+ action corre.c
+ action cursor.c
+ action cutpaste.c
+ action dispcur.c
+ action draw.c
+ action hextile.c
+ action httpd.c
+ action kbdptr.c
+ action keyboard.h
+ action loginauth.c
+ action rdp.c
+ action rfb.h
+ action rfbkeyb.c
+ action rfbmouse.c
+ action rfbproto.h
+ action rfbserver.c
+ action rre.c
+ action sockets.c
+ action sprite.c
+ action sprite.h
+ action spritest.h
+ action stats.c
+ action tableinitcmtemplate.c
+ action tableinittctemplate.c
+ action tabletranstemplate.c
+ action tight.c
+ action translate.c
+ action vncauth.c
+ action vncauth.h
+ action vncext.c
+ action xistubs.c
+ action zlib.c
+}
+
+#########
+#
+# Helper functions
+#
+#########
+
+error() {
+ echo
+ echo \ \ \ error:\ \ \ $1
+ exit 1
+}
+
+# printing out what's going on
+run_module() {
+ # $1 module
+ # $2 explanation
+ echo -n $EXPLANATION for $1 module ...\
+ symlink_$1
+ echo DONE
+}
+
+run() {
+ # $1 what to do
+ # $2 explanation
+
+ ACTION=$1 EXPLANATION=$2 run_module vnc
+}
+
+src_dir() {
+ REAL_SRC_DIR=$SRC_DIR/$1
+ if [ ! -d $REAL_SRC_DIR ] ; then
+ error "Source directory $REAL_SRC_DIR does not exist"
+ fi
+}
+
+dst_dir() {
+ REAL_DST_DIR=$DST_DIR/$1
+ if [ ! -d $REAL_DST_DIR ] ; then
+ mkdir -p $REAL_DST_DIR
+ fi
+}
+
+action() {
+ if [ -z $2 ] ; then
+ $ACTION $REAL_SRC_DIR/$1 $REAL_DST_DIR/$1
+ else
+ $ACTION $REAL_SRC_DIR/$1 $REAL_DST_DIR/$2
+ fi
+}
+
+usage() {
+ echo symlink.sh src-dir dst-dir
+ echo src-dir: the xc directory of the monolithic source tree
+ echo dst-dir: the modular source tree containing proto, app, lib, ...
+}
+
+# Check commandline args
+check_args() {
+ if [ -z $1 ] ; then
+ echo Missing source dir
+ usage
+ exit 1
+ fi
+
+ if [ -z $2 ] ; then
+ echo Missing destination dir
+ usage
+ exit 1
+ fi
+
+ if [ ! -d $1 ] ; then
+ echo $1 is not a dir
+ usage
+ exit 1
+ fi
+
+ if [ ! -d $2 ] ; then
+ echo $2 is not a dir
+ usage
+ exit 1
+ fi
+
+ if [ $1 = $2 ] ; then
+ echo source and destination can\'t be the same
+ usage
+ exit 1
+ fi
+
+ D=`dirname "$relpath"`
+ B=`basename "$relpath"`
+ abspath="`cd \"$D\" 2>/dev/null && pwd || echo \"$D\"`/$B"
+
+ SRC_DIR=`( cd $1 ; pwd )`
+ DST_DIR=`(cd $2 ; pwd )`
+}
+
+main $1 $2
--- xorg-server-1.7.4/hw/vnc/tableinitcmtemplate.c
+++ xorg-server-1.7.4/hw/vnc/tableinitcmtemplate.c
@@ -0,0 +1,93 @@
+/*
+ * tableinitcmtemplate.c - template for initialising lookup tables for
+ * translation from a colour map to true colour.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with a different definition of the macro OUT.
+ * For each value of OUT, this file defines a function which allocates an
+ * appropriately sized lookup table and initialises it.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#if !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define OUT_T CONCAT2E(CARD,OUT)
+#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
+#define rfbInitColourMapSingleTableOUT \
+ CONCAT2E(rfbInitColourMapSingleTable,OUT)
+
+static void
+rfbInitColourMapSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ VNCSCREENPTR(pScreen);
+ int i, r, g, b;
+ OUT_T *t;
+ EntryPtr pent;
+ int nEntries = 1 << in->bitsPerPixel;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * sizeof(OUT_T));
+ t = (OUT_T *)*table;
+
+#if XFREE86VNC
+ pent = (EntryPtr)&miInstalledMaps[pScreen->myNum]->red[0];
+#else
+ pent = (EntryPtr)&pVNC->rfbInstalledColormap->red[0];
+#endif
+
+ for (i = 0; i < nEntries; i++) {
+ if (pent->fShared) {
+ r = pent->co.shco.red->color;
+ g = pent->co.shco.green->color;
+ b = pent->co.shco.blue->color;
+ } else {
+ r = pent->co.local.red;
+ g = pent->co.local.green;
+ b = pent->co.local.blue;
+ }
+ t[i] = ((((r * out->redMax + 32767) / 65535) << out->redShift) |
+ (((g * out->greenMax + 32767) / 65535) << out->greenShift) |
+ (((b * out->blueMax + 32767) / 65535) << out->blueShift));
+#if (OUT != 8)
+ if (out->bigEndian != in->bigEndian) {
+ t[i] = SwapOUT(t[i]);
+ }
+#endif
+ pent++;
+ }
+}
+
+#undef OUT_T
+#undef SwapOUT
+#undef rfbInitColourMapSingleTableOUT
--- xorg-server-1.7.4/hw/vnc/tableinittctemplate.c
+++ xorg-server-1.7.4/hw/vnc/tableinittctemplate.c
@@ -0,0 +1,146 @@
+/*
+ * tableinittctemplate.c - template for initialising lookup tables for
+ * truecolour to truecolour translation.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with a different definition of the macro OUT.
+ * For each value of OUT, this file defines two functions for initialising
+ * lookup tables. One is for truecolour translation using a single lookup
+ * table, the other is for truecolour translation using three separate
+ * lookup tables for the red, green and blue values.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#if !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define OUT_T CONCAT2E(CARD,OUT)
+#define SwapOUT(x) CONCAT2E(Swap,OUT(x))
+#define rfbInitTrueColourSingleTableOUT \
+ CONCAT2E(rfbInitTrueColourSingleTable,OUT)
+#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT)
+#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT)
+
+static void
+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
+ int swap);
+
+
+/*
+ * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour
+ * translation.
+ */
+
+static void
+rfbInitTrueColourSingleTableOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ int i;
+ int inRed, inGreen, inBlue, outRed, outGreen, outBlue;
+ OUT_T *t;
+ int nEntries = 1 << in->bitsPerPixel;
+
+ if (*table) free(*table);
+ *table = (char *)malloc(nEntries * sizeof(OUT_T));
+ t = (OUT_T *)*table;
+
+ for (i = 0; i < nEntries; i++) {
+ inRed = (i >> in->redShift) & in->redMax;
+ inGreen = (i >> in->greenShift) & in->greenMax;
+ inBlue = (i >> in->blueShift) & in->blueMax;
+
+ outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax;
+ outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax;
+ outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax;
+
+ t[i] = ((outRed << out->redShift) |
+ (outGreen << out->greenShift) |
+ (outBlue << out->blueShift));
+#if (OUT != 8)
+ if (out->bigEndian != in->bigEndian) {
+ t[i] = SwapOUT(t[i]);
+ }
+#endif
+ }
+}
+
+
+/*
+ * rfbInitTrueColourRGBTables sets up three separate lookup tables for the
+ * red, green and blue values.
+ */
+
+static void
+rfbInitTrueColourRGBTablesOUT (ScreenPtr pScreen, char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out)
+{
+ OUT_T *redTable;
+ OUT_T *greenTable;
+ OUT_T *blueTable;
+
+ if (*table) free(*table);
+ *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3)
+ * sizeof(OUT_T));
+ redTable = (OUT_T *)*table;
+ greenTable = redTable + in->redMax + 1;
+ blueTable = greenTable + in->greenMax + 1;
+
+ rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax,
+ out->redShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax,
+ out->greenShift, (out->bigEndian != in->bigEndian));
+ rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax,
+ out->blueShift, (out->bigEndian != in->bigEndian));
+}
+
+static void
+rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift,
+ int swap)
+{
+ int i;
+ int nEntries = inMax + 1;
+
+ for (i = 0; i < nEntries; i++) {
+ table[i] = ((i * outMax + inMax / 2) / inMax) << outShift;
+#if (OUT != 8)
+ if (swap) {
+ table[i] = SwapOUT(table[i]);
+ }
+#endif
+ }
+}
+
+#undef OUT_T
+#undef SwapOUT
+#undef rfbInitTrueColourSingleTableOUT
+#undef rfbInitTrueColourRGBTablesOUT
+#undef rfbInitOneRGBTableOUT
--- xorg-server-1.7.4/hw/vnc/tabletranstemplate.c
+++ xorg-server-1.7.4/hw/vnc/tabletranstemplate.c
@@ -0,0 +1,135 @@
+/*
+ * tabletranstemplate.c - template for translation using lookup tables.
+ *
+ * This file shouldn't be compiled. It is included multiple times by
+ * translate.c, each time with different definitions of the macros IN and OUT.
+ *
+ * For each pair of values IN and OUT, this file defines two functions for
+ * translating a given rectangle of pixel data. One uses a single lookup
+ * table, and the other uses three separate lookup tables for the red, green
+ * and blue values.
+ *
+ * I know this code isn't nice to read because of all the macros, but
+ * efficiency is important here.
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#if !defined(IN) || !defined(OUT)
+#error "This file shouldn't be compiled."
+#error "It is included as part of translate.c"
+#endif
+
+#define IN_T CONCAT2E(CARD,IN)
+#define OUT_T CONCAT2E(CARD,OUT)
+#define rfbTranslateWithSingleTableINtoOUT \
+ CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT)
+#define rfbTranslateWithRGBTablesINtoOUT \
+ CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT)
+
+/*
+ * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data
+ * using a single lookup table.
+ */
+
+static void
+rfbTranslateWithSingleTableINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ unsigned char *optr,
+ int bytesBetweenInputLines,
+ int width, int height,
+ int x, int y)
+{
+ IN_T *ip;
+ OUT_T *op = (OUT_T *)optr;
+ OUT_T *opLineEnd;
+ OUT_T *t = (OUT_T *)table;
+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum];
+ int truewidth = PixmapBytePad(width, in->bitsPerPixel);
+ unsigned char *iptr = malloc(truewidth * height * in->bitsPerPixel / 8);
+ int ipextra = truewidth - width;
+ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)iptr);
+ ip = (IN_T *)iptr;
+
+ while (height > 0) {
+ opLineEnd = op + width;
+
+ while (op < opLineEnd) {
+ *(op++) = t[*(ip++)];
+ }
+
+ ip += ipextra;
+ height--;
+ }
+ free(iptr);
+}
+
+
+/*
+ * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data
+ * using three separate lookup tables for the red, green and blue values.
+ */
+
+static void
+rfbTranslateWithRGBTablesINtoOUT (ScreenPtr pScreen, char *table, rfbPixelFormat *in,
+ rfbPixelFormat *out,
+ unsigned char *optr,
+ int bytesBetweenInputLines,
+ int width, int height,
+ int x, int y)
+{
+ IN_T *ip;
+ OUT_T *op = (OUT_T *)optr;
+ OUT_T *opLineEnd;
+ OUT_T *redTable = (OUT_T *)table;
+ OUT_T *greenTable = redTable + in->redMax + 1;
+ OUT_T *blueTable = greenTable + in->greenMax + 1;
+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum];
+ int truewidth = PixmapBytePad(width, in->bitsPerPixel);
+ unsigned char *iptr = malloc(truewidth * height * in->bitsPerPixel / 8);
+ int ipextra = truewidth - width;
+ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)iptr);
+ ip = (IN_T *)iptr;
+
+ while (height > 0) {
+ opLineEnd = op + width;
+
+ while (op < opLineEnd) {
+ *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] |
+ greenTable[(*ip >> in->greenShift) & in->greenMax] |
+ blueTable[(*ip >> in->blueShift) & in->blueMax]);
+ ip++;
+ }
+ ip += ipextra;
+ height--;
+ }
+ free(iptr);
+}
+
+#undef IN_T
+#undef OUT_T
+#undef rfbTranslateWithSingleTableINtoOUT
+#undef rfbTranslateWithRGBTablesINtoOUT
--- xorg-server-1.7.4/hw/vnc/tight.c
+++ xorg-server-1.7.4/hw/vnc/tight.c
@@ -0,0 +1,1827 @@
+/*
+ * tight.c
+ *
+ * Routines to implement Tight Encoding
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include "rfb.h"
+#include <jpeglib.h>
+
+
+/* Note: The following constant should not be changed. */
+#define TIGHT_MIN_TO_COMPRESS 12
+
+/* The parameters below may be adjusted. */
+#define MIN_SPLIT_RECT_SIZE 4096
+#define MIN_SOLID_SUBRECT_SIZE 2048
+#define MAX_SPLIT_TILE_SIZE 16
+
+/* May be set to TRUE with "-lazytight" Xvnc option. */
+Bool rfbTightDisableGradient = FALSE;
+
+/* This variable is set on every rfbSendRectEncodingTight() call. */
+static Bool usePixelFormat24;
+
+
+/* Compression level stuff. The following array contains various
+ encoder parameters for each of 10 compression levels (0..9).
+ Last three parameters correspond to JPEG quality levels (0..9). */
+
+typedef struct TIGHT_CONF_s {
+ int maxRectSize, maxRectWidth;
+ int monoMinRectSize, gradientMinRectSize;
+ int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel;
+ int gradientThreshold, gradientThreshold24;
+ int idxMaxColorsDivisor;
+ int jpegQuality, jpegThreshold, jpegThreshold24;
+} TIGHT_CONF;
+
+static TIGHT_CONF tightConf[10] = {
+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 },
+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 },
+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 },
+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 },
+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 },
+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 },
+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 },
+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 },
+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 },
+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }
+};
+
+/* Stuff dealing with palettes. */
+
+typedef struct COLOR_LIST_s {
+ struct COLOR_LIST_s *next;
+ int idx;
+ CARD32 rgb;
+} COLOR_LIST;
+
+typedef struct PALETTE_ENTRY_s {
+ COLOR_LIST *listNode;
+ int numPixels;
+} PALETTE_ENTRY;
+
+typedef struct PALETTE_s {
+ PALETTE_ENTRY entry[256];
+ COLOR_LIST *hash[256];
+ COLOR_LIST list[256];
+} PALETTE;
+
+static int paletteNumColors, paletteMaxColors;
+static CARD32 monoBackground, monoForeground;
+static PALETTE palette;
+
+/* Pointers to dynamically-allocated buffers. */
+
+static int tightBeforeBufSize = 0;
+static unsigned char *tightBeforeBuf = NULL;
+
+static int tightAfterBufSize = 0;
+static unsigned char *tightAfterBuf = NULL;
+
+static int *prevRowBuf = NULL;
+
+
+/* Prototypes for static functions. */
+
+static void FindBestSolidArea (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 colorValue, int *w_ptr, int *h_ptr);
+static void ExtendSolidArea (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 colorValue,
+ int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr);
+static Bool CheckSolidTile (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile8 (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile16 (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+static Bool CheckSolidTile32 (ScreenPtr pScreen, int x, int y, int w, int h,
+ CARD32 *colorPtr, Bool needSameColor);
+
+static Bool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h);
+static Bool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h);
+static Bool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h);
+
+static Bool SendSolidRect (rfbClientPtr cl);
+static Bool SendMonoRect (rfbClientPtr cl, int w, int h);
+static Bool SendIndexedRect (rfbClientPtr cl, int w, int h);
+static Bool SendFullColorRect (rfbClientPtr cl, int w, int h);
+static Bool SendGradientRect (rfbClientPtr cl, int w, int h);
+
+static Bool CompressData(rfbClientPtr cl, int streamId, int dataLen,
+ int zlibLevel, int zlibStrategy);
+static Bool SendCompressedData(rfbClientPtr cl, int compressedLen);
+
+static void FillPalette8(int count);
+static void FillPalette16(int count);
+static void FillPalette32(int count);
+
+static void PaletteReset(void);
+static int PaletteInsert(CARD32 rgb, int numPixels, int bpp);
+
+static void Pack24(ScreenPtr pScreen, unsigned char *buf, rfbPixelFormat *fmt, int count);
+
+static void EncodeIndexedRect16(CARD8 *buf, int count);
+static void EncodeIndexedRect32(CARD8 *buf, int count);
+
+static void EncodeMonoRect8(CARD8 *buf, int w, int h);
+static void EncodeMonoRect16(CARD8 *buf, int w, int h);
+static void EncodeMonoRect32(CARD8 *buf, int w, int h);
+
+static void FilterGradient24(ScreenPtr pScreen, unsigned char *buf, rfbPixelFormat *fmt, int w, int h);
+static void FilterGradient16(ScreenPtr pScreen, CARD16 *buf, rfbPixelFormat *fmt, int w, int h);
+static void FilterGradient32(ScreenPtr pScreen, CARD32 *buf, rfbPixelFormat *fmt, int w, int h);
+
+static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h);
+
+static Bool SendJpegRect(rfbClientPtr cl, const CARD8 *buffer, int w, int h, int quality);
+static void PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width);
+static void PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width);
+static void PrepareRowForJpeg16(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width);
+static void PrepareRowForJpeg32(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, int row, int width);
+
+static void JpegInitDestination(j_compress_ptr cinfo);
+static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo);
+static void JpegTermDestination(j_compress_ptr cinfo);
+static void JpegSetDstManager(j_compress_ptr cinfo);
+
+
+/*
+ * Tight encoding implementation.
+ */
+
+int
+rfbNumCodedRectsTight(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int maxRectSize, maxRectWidth;
+ int subrectMaxWidth, subrectMaxHeight;
+
+ /* No matter how many rectangles we will send if LastRect markers
+ are used to terminate rectangle stream. */
+ if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE)
+ return 0;
+
+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize;
+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth;
+
+ if (w > maxRectWidth || w * h > maxRectSize) {
+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ subrectMaxHeight = maxRectSize / subrectMaxWidth;
+ return (((w - 1) / maxRectWidth + 1) *
+ ((h - 1) / subrectMaxHeight + 1));
+ } else {
+ return 1;
+ }
+}
+
+Bool
+rfbSendRectEncodingTight(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int nMaxRows;
+ CARD32 colorValue;
+ int dx, dy, dw, dh;
+ int x_best, y_best, w_best, h_best;
+
+ if ( cl->format.depth == 24 && cl->format.redMax == 0xFF &&
+ cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) {
+ usePixelFormat24 = TRUE;
+ } else {
+ usePixelFormat24 = FALSE;
+ }
+
+ if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE)
+ return SendRectSimple(cl, x, y, w, h);
+
+ /* Make sure we can write at least one pixel into tightBeforeBuf. */
+
+ if (tightBeforeBufSize < 4) {
+ tightBeforeBufSize = 4;
+ if (tightBeforeBuf == NULL)
+ tightBeforeBuf = (unsigned char *)xalloc(tightBeforeBufSize);
+ else
+ tightBeforeBuf = (unsigned char *)xrealloc(tightBeforeBuf,
+ tightBeforeBufSize);
+ }
+
+ /* Calculate maximum number of rows in one non-solid rectangle. */
+
+ {
+ int maxRectSize, maxRectWidth, nMaxWidth;
+
+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize;
+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth;
+ nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ nMaxRows = maxRectSize / nMaxWidth;
+ }
+
+ /* Try to find large solid-color areas and send them separately. */
+
+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
+
+ /* If a rectangle becomes too large, send its upper part now. */
+
+ if (dy - y >= nMaxRows) {
+ if (!SendRectSimple(cl, x, y, w, nMaxRows))
+ return 0;
+ y += nMaxRows;
+ h -= nMaxRows;
+ }
+
+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
+ MAX_SPLIT_TILE_SIZE : (y + h - dy);
+
+ for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) {
+
+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ?
+ MAX_SPLIT_TILE_SIZE : (x + w - dx);
+
+ if (CheckSolidTile(cl->pScreen, dx, dy, dw, dh, &colorValue, FALSE)) {
+
+ /* Get dimensions of solid-color area. */
+
+ FindBestSolidArea(cl->pScreen, dx, dy, w - (dx - x), h - (dy - y),
+ colorValue, &w_best, &h_best);
+
+ /* Make sure a solid rectangle is large enough
+ (or the whole rectangle is of the same color). */
+
+ if ( w_best * h_best != w * h &&
+ w_best * h_best < MIN_SOLID_SUBRECT_SIZE )
+ continue;
+
+ /* Try to extend solid rectangle to maximum size. */
+
+ x_best = dx; y_best = dy;
+ ExtendSolidArea(cl->pScreen, x, y, w, h, colorValue,
+ &x_best, &y_best, &w_best, &h_best);
+
+ /* Send rectangles at top and left to solid-color area. */
+
+ if ( y_best != y &&
+ !SendRectSimple(cl, x, y, w, y_best-y) )
+ return FALSE;
+ if ( x_best != x &&
+ !rfbSendRectEncodingTight(cl, x, y_best,
+ x_best-x, h_best) )
+ return FALSE;
+
+ /* Send solid-color rectangle. */
+
+ if (!SendTightHeader(cl, x_best, y_best, w_best, h_best))
+ return FALSE;
+
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable,
+ &pVNC->rfbServerFormat,
+ &cl->format, tightBeforeBuf,
+ pVNC->paddedWidthInBytes, 1, 1,
+ x_best, y_best);
+
+ if (!SendSolidRect(cl))
+ return FALSE;
+
+ /* Send remaining rectangles (at right and bottom). */
+
+ if ( x_best + w_best != x + w &&
+ !rfbSendRectEncodingTight(cl, x_best+w_best, y_best,
+ w-(x_best-x)-w_best, h_best) )
+ return FALSE;
+ if ( y_best + h_best != y + h &&
+ !rfbSendRectEncodingTight(cl, x, y_best+h_best,
+ w, h-(y_best-y)-h_best) )
+ return FALSE;
+
+ /* Return after all recursive calls are done. */
+
+ return TRUE;
+ }
+
+ }
+
+ }
+
+ /* No suitable solid-color rectangles found. */
+
+ return SendRectSimple(cl, x, y, w, h);
+}
+
+static void
+FindBestSolidArea(pScreen, x, y, w, h, colorValue, w_ptr, h_ptr)
+ ScreenPtr pScreen;
+ int x, y, w, h;
+ CARD32 colorValue;
+ int *w_ptr, *h_ptr;
+{
+ int dx, dy, dw, dh;
+ int w_prev;
+ int w_best = 0, h_best = 0;
+
+ w_prev = w;
+
+ for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) {
+
+ dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ?
+ MAX_SPLIT_TILE_SIZE : (y + h - dy);
+ dw = (w_prev > MAX_SPLIT_TILE_SIZE) ?
+ MAX_SPLIT_TILE_SIZE : w_prev;
+
+ if (!CheckSolidTile(pScreen, x, dy, dw, dh, &colorValue, TRUE))
+ break;
+
+ for (dx = x + dw; dx < x + w_prev;) {
+ dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ?
+ MAX_SPLIT_TILE_SIZE : (x + w_prev - dx);
+ if (!CheckSolidTile(pScreen, dx, dy, dw, dh, &colorValue, TRUE))
+ break;
+ dx += dw;
+ }
+
+ w_prev = dx - x;
+ if (w_prev * (dy + dh - y) > w_best * h_best) {
+ w_best = w_prev;
+ h_best = dy + dh - y;
+ }
+ }
+
+ *w_ptr = w_best;
+ *h_ptr = h_best;
+}
+
+static void
+ExtendSolidArea(pScreen, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr)
+ ScreenPtr pScreen;
+ int x, y, w, h;
+ CARD32 colorValue;
+ int *x_ptr, *y_ptr, *w_ptr, *h_ptr;
+{
+ int cx, cy;
+
+ /* Try to extend the area upwards. */
+ for ( cy = *y_ptr - 1;
+ cy >= y && CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
+ cy-- );
+ *h_ptr += *y_ptr - (cy + 1);
+ *y_ptr = cy + 1;
+
+ /* ... downwards. */
+ for ( cy = *y_ptr + *h_ptr;
+ cy < y + h &&
+ CheckSolidTile(pScreen, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE);
+ cy++ );
+ *h_ptr += cy - (*y_ptr + *h_ptr);
+
+ /* ... to the left. */
+ for ( cx = *x_ptr - 1;
+ cx >= x && CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
+ cx-- );
+ *w_ptr += *x_ptr - (cx + 1);
+ *x_ptr = cx + 1;
+
+ /* ... to the right. */
+ for ( cx = *x_ptr + *w_ptr;
+ cx < x + w &&
+ CheckSolidTile(pScreen, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE);
+ cx++ );
+ *w_ptr += cx - (*x_ptr + *w_ptr);
+}
+
+/*
+ * Check if a rectangle is all of the same color. If needSameColor is
+ * set to non-zero, then also check that its color equals to the
+ * *colorPtr value. The result is 1 if the test is successfull, and in
+ * that case new color will be stored in *colorPtr.
+ */
+
+static Bool
+CheckSolidTile(pScreen, x, y, w, h, colorPtr, needSameColor)
+ ScreenPtr pScreen;
+ int x, y, w, h;
+ CARD32 *colorPtr;
+ Bool needSameColor;
+{
+ VNCSCREENPTR(pScreen);
+ switch(pVNC->rfbServerFormat.bitsPerPixel) {
+ case 32:
+ return CheckSolidTile32(pScreen, x, y, w, h, colorPtr, needSameColor);
+ case 16:
+ return CheckSolidTile16(pScreen, x, y, w, h, colorPtr, needSameColor);
+ default:
+ return CheckSolidTile8(pScreen, x, y, w, h, colorPtr, needSameColor);
+ }
+}
+
+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \
+ \
+static Bool \
+CheckSolidTile##bpp(pScreen, x, y, w, h, colorPtr, needSameColor) \
+ ScreenPtr pScreen; \
+ int x, y; \
+ CARD32 *colorPtr; \
+ Bool needSameColor; \
+{ \
+ VNCSCREENPTR(pScreen); \
+ CARD##bpp *fbptr; \
+ CARD##bpp colorValue; \
+ int dx, dy; \
+ \
+ fbptr = (CARD##bpp *) \
+ &pVNC->pfbMemory[y * pVNC->paddedWidthInBytes + x * (bpp/8)]; \
+ \
+ colorValue = *fbptr; \
+ if (needSameColor && (CARD32)colorValue != *colorPtr) \
+ return FALSE; \
+ \
+ for (dy = 0; dy < h; dy++) { \
+ for (dx = 0; dx < w; dx++) { \
+ if (colorValue != fbptr[dx]) \
+ return FALSE; \
+ } \
+ fbptr = (CARD##bpp *)((CARD8 *)fbptr + pVNC->paddedWidthInBytes); \
+ } \
+ \
+ *colorPtr = (CARD32)colorValue; \
+ return TRUE; \
+}
+
+DEFINE_CHECK_SOLID_FUNCTION(8)
+DEFINE_CHECK_SOLID_FUNCTION(16)
+DEFINE_CHECK_SOLID_FUNCTION(32)
+
+static Bool
+SendRectSimple(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ int maxBeforeSize, maxAfterSize;
+ int maxRectSize, maxRectWidth;
+ int subrectMaxWidth, subrectMaxHeight;
+ int dx, dy;
+ int rw, rh;
+
+ maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize;
+ maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth;
+
+ maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8);
+ maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12;
+
+ if (tightBeforeBufSize < maxBeforeSize) {
+ tightBeforeBufSize = maxBeforeSize;
+ if (tightBeforeBuf == NULL)
+ tightBeforeBuf = (unsigned char *)xalloc(tightBeforeBufSize);
+ else
+ tightBeforeBuf = (unsigned char *)xrealloc(tightBeforeBuf,
+ tightBeforeBufSize);
+ }
+
+ if (tightAfterBufSize < maxAfterSize) {
+ tightAfterBufSize = maxAfterSize;
+ if (tightAfterBuf == NULL)
+ tightAfterBuf = (unsigned char *)xalloc(tightAfterBufSize);
+ else
+ tightAfterBuf = (unsigned char *)xrealloc(tightAfterBuf,
+ tightAfterBufSize);
+ }
+
+ if (w > maxRectWidth || w * h > maxRectSize) {
+ subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w;
+ subrectMaxHeight = maxRectSize / subrectMaxWidth;
+
+ for (dy = 0; dy < h; dy += subrectMaxHeight) {
+ for (dx = 0; dx < w; dx += maxRectWidth) {
+ rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx;
+ rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy;
+ if (!SendSubrect(cl, x+dx, y+dy, rw, rh))
+ return FALSE;
+ }
+ }
+ } else {
+ if (!SendSubrect(cl, x, y, w, h))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+SendSubrect(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ Bool success = FALSE;
+
+ /* Send pending data if there is more than 128 bytes. */
+ if (pVNC->ublen > 128) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if (!SendTightHeader(cl, x, y, w, h))
+ return FALSE;
+
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable, &pVNC->rfbServerFormat,
+ &cl->format, tightBeforeBuf,
+ pVNC->paddedWidthInBytes, w, h, x, y);
+
+ paletteMaxColors = w * h / tightConf[cl->tightCompressLevel].idxMaxColorsDivisor;
+ if ( paletteMaxColors < 2 &&
+ w * h >= tightConf[cl->tightCompressLevel].monoMinRectSize ) {
+ paletteMaxColors = 2;
+ }
+ switch (cl->format.bitsPerPixel) {
+ case 8:
+ FillPalette8(w * h);
+ break;
+ case 16:
+ FillPalette16(w * h);
+ break;
+ default:
+ FillPalette32(w * h);
+ }
+
+ switch (paletteNumColors) {
+ case 0:
+ /* Truecolor image */
+ if (DetectSmoothImage(cl, &cl->format, w, h)) {
+ if (cl->tightQualityLevel != -1) {
+ success = SendJpegRect(cl, tightBeforeBuf, w, h,
+ tightConf[cl->tightQualityLevel].jpegQuality);
+ } else {
+ success = SendGradientRect(cl, w, h);
+ }
+ } else {
+ success = SendFullColorRect(cl, w, h);
+ }
+ break;
+ case 1:
+ /* Solid rectangle */
+ success = SendSolidRect(cl);
+ break;
+ case 2:
+ /* Two-color rectangle */
+ success = SendMonoRect(cl, w, h);
+ break;
+ default:
+ /* Up to 256 different colors */
+ if ( paletteNumColors > 96 &&
+ cl->tightQualityLevel != -1 && cl->tightQualityLevel <= 3 &&
+ DetectSmoothImage(cl, &cl->format, w, h) ) {
+ success = SendJpegRect(cl, tightBeforeBuf, w, h,
+ tightConf[cl->tightQualityLevel].jpegQuality);
+ } else {
+ success = SendIndexedRect(cl, w, h);
+ }
+ }
+ return success;
+}
+
+static Bool
+SendTightHeader(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingTight);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbRectanglesSent[rfbEncodingTight]++;
+ cl->rfbBytesSent[rfbEncodingTight] += sz_rfbFramebufferUpdateRectHeader;
+
+ return TRUE;
+}
+
+/*
+ * Subencoding implementations.
+ */
+
+static Bool
+SendSolidRect(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int len;
+
+ if (usePixelFormat24) {
+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, 1);
+ len = 3;
+ } else
+ len = cl->format.bitsPerPixel / 8;
+
+ if (pVNC->ublen + 1 + len > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightFill << 4);
+ memcpy (&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, len);
+ pVNC->ublen += len;
+
+ cl->rfbBytesSent[rfbEncodingTight] += len + 1;
+
+ return TRUE;
+}
+
+static Bool
+SendMonoRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int streamId = 1;
+ int paletteLen, dataLen;
+
+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+ 2 * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ /* Prepare tight encoding header. */
+ dataLen = (w + 7) / 8;
+ dataLen *= h;
+
+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette;
+ pVNC->updateBuf[pVNC->ublen++] = 1;
+
+ /* Prepare palette, convert image. */
+ switch (cl->format.bitsPerPixel) {
+
+ case 32:
+ EncodeMonoRect32((CARD8 *)tightBeforeBuf, w, h);
+
+ ((CARD32 *)tightAfterBuf)[0] = monoBackground;
+ ((CARD32 *)tightAfterBuf)[1] = monoForeground;
+ if (usePixelFormat24) {
+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, 2);
+ paletteLen = 6;
+ } else
+ paletteLen = 8;
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteLen);
+ pVNC->ublen += paletteLen;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteLen;
+ break;
+
+ case 16:
+ EncodeMonoRect16((CARD8 *)tightBeforeBuf, w, h);
+
+ ((CARD16 *)tightAfterBuf)[0] = (CARD16)monoBackground;
+ ((CARD16 *)tightAfterBuf)[1] = (CARD16)monoForeground;
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, 4);
+ pVNC->ublen += 4;
+ cl->rfbBytesSent[rfbEncodingTight] += 7;
+ break;
+
+ default:
+ EncodeMonoRect8((CARD8 *)tightBeforeBuf, w, h);
+
+ pVNC->updateBuf[pVNC->ublen++] = (char)monoBackground;
+ pVNC->updateBuf[pVNC->ublen++] = (char)monoForeground;
+ cl->rfbBytesSent[rfbEncodingTight] += 5;
+ }
+
+ return CompressData(cl, streamId, dataLen,
+ tightConf[cl->tightCompressLevel].monoZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendIndexedRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int streamId = 2;
+ int i, entryLen;
+
+ if ( (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 6 +
+ paletteNumColors * cl->format.bitsPerPixel / 8) > UPDATE_BUF_SIZE ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ /* Prepare tight encoding header. */
+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterPalette;
+ pVNC->updateBuf[pVNC->ublen++] = (char)(paletteNumColors - 1);
+
+ /* Prepare palette, convert image. */
+ switch (cl->format.bitsPerPixel) {
+
+ case 32:
+ EncodeIndexedRect32((CARD8 *)tightBeforeBuf, w * h);
+
+ for (i = 0; i < paletteNumColors; i++) {
+ ((CARD32 *)tightAfterBuf)[i] =
+ palette.entry[i].listNode->rgb;
+ }
+ if (usePixelFormat24) {
+ Pack24(cl->pScreen, tightAfterBuf, &cl->format, paletteNumColors);
+ entryLen = 3;
+ } else
+ entryLen = 4;
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * entryLen);
+ pVNC->ublen += paletteNumColors * entryLen;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * entryLen;
+ break;
+
+ case 16:
+ EncodeIndexedRect16((CARD8 *)tightBeforeBuf, w * h);
+
+ for (i = 0; i < paletteNumColors; i++) {
+ ((CARD16 *)tightAfterBuf)[i] =
+ (CARD16)palette.entry[i].listNode->rgb;
+ }
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightAfterBuf, paletteNumColors * 2);
+ pVNC->ublen += paletteNumColors * 2;
+ cl->rfbBytesSent[rfbEncodingTight] += 3 + paletteNumColors * 2;
+ break;
+
+ default:
+ return FALSE; /* Should never happen. */
+ }
+
+ return CompressData(cl, streamId, w * h,
+ tightConf[cl->tightCompressLevel].idxZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendFullColorRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int streamId = 0;
+ int len;
+
+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ pVNC->updateBuf[pVNC->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */
+ cl->rfbBytesSent[rfbEncodingTight]++;
+
+ if (usePixelFormat24) {
+ Pack24(cl->pScreen, tightBeforeBuf, &cl->format, w * h);
+ len = 3;
+ } else
+ len = cl->format.bitsPerPixel / 8;
+
+ return CompressData(cl, streamId, w * h * len,
+ tightConf[cl->tightCompressLevel].rawZlibLevel,
+ Z_DEFAULT_STRATEGY);
+}
+
+static Bool
+SendGradientRect(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int streamId = 3;
+ int len;
+
+ if (cl->format.bitsPerPixel == 8)
+ return SendFullColorRect(cl, w, h);
+
+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ if (prevRowBuf == NULL)
+ prevRowBuf = (int *)xalloc(2048 * 3 * sizeof(int));
+
+ pVNC->updateBuf[pVNC->ublen++] = (streamId | rfbTightExplicitFilter) << 4;
+ pVNC->updateBuf[pVNC->ublen++] = rfbTightFilterGradient;
+ cl->rfbBytesSent[rfbEncodingTight] += 2;
+
+ if (usePixelFormat24) {
+ FilterGradient24(cl->pScreen, tightBeforeBuf, &cl->format, w, h);
+ len = 3;
+ } else if (cl->format.bitsPerPixel == 32) {
+ FilterGradient32(cl->pScreen, (CARD32 *)tightBeforeBuf, &cl->format, w, h);
+ len = 4;
+ } else {
+ FilterGradient16(cl->pScreen, (CARD16 *)tightBeforeBuf, &cl->format, w, h);
+ len = 2;
+ }
+
+ return CompressData(cl, streamId, w * h * len,
+ tightConf[cl->tightCompressLevel].gradientZlibLevel,
+ Z_FILTERED);
+}
+
+/**
+ * Compress the data in the tightBeforeBuf buffer.
+ * \param dataLen - amount of data in tightBeforeBuf to compress, in bytes
+ */
+static Bool
+CompressData(cl, streamId, dataLen, zlibLevel, zlibStrategy)
+ rfbClientPtr cl;
+ int streamId, dataLen, zlibLevel, zlibStrategy;
+{
+ VNCSCREENPTR(cl->pScreen);
+ z_streamp pz;
+ int err;
+
+ if (dataLen < TIGHT_MIN_TO_COMPRESS) {
+ memcpy(&pVNC->updateBuf[pVNC->ublen], tightBeforeBuf, dataLen);
+ pVNC->ublen += dataLen;
+ cl->rfbBytesSent[rfbEncodingTight] += dataLen;
+ return TRUE;
+ }
+
+ pz = &cl->zsStruct[streamId];
+
+ /* Initialize compression stream if needed. */
+ if (!cl->zsActive[streamId]) {
+ pz->zalloc = Z_NULL;
+ pz->zfree = Z_NULL;
+ pz->opaque = Z_NULL;
+
+ err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS,
+ MAX_MEM_LEVEL, zlibStrategy);
+ if (err != Z_OK)
+ return FALSE;
+
+ cl->zsActive[streamId] = TRUE;
+ cl->zsLevel[streamId] = zlibLevel;
+ }
+
+ /* Prepare buffer pointers. */
+ pz->next_in = (Bytef *)tightBeforeBuf;
+ pz->avail_in = dataLen;
+ pz->next_out = (Bytef *)tightAfterBuf;
+ pz->avail_out = tightAfterBufSize;
+
+ /* Change compression parameters if needed. */
+ if (zlibLevel != cl->zsLevel[streamId]) {
+ if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) {
+ return FALSE;
+ }
+ cl->zsLevel[streamId] = zlibLevel;
+ }
+
+ /* Actual compression. */
+ if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK ||
+ pz->avail_in != 0 || pz->avail_out == 0 ) {
+ return FALSE;
+ }
+
+ return SendCompressedData(cl, tightAfterBufSize - pz->avail_out);
+}
+
+static Bool SendCompressedData(cl, compressedLen)
+ rfbClientPtr cl;
+ int compressedLen;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int i, portionLen;
+
+ pVNC->updateBuf[pVNC->ublen++] = compressedLen & 0x7F;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ if (compressedLen > 0x7F) {
+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80;
+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 7 & 0x7F;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ if (compressedLen > 0x3FFF) {
+ pVNC->updateBuf[pVNC->ublen-1] |= 0x80;
+ pVNC->updateBuf[pVNC->ublen++] = compressedLen >> 14 & 0xFF;
+ cl->rfbBytesSent[rfbEncodingTight]++;
+ }
+ }
+
+ portionLen = UPDATE_BUF_SIZE;
+ for (i = 0; i < compressedLen; i += portionLen) {
+ if (i + portionLen > compressedLen) {
+ portionLen = compressedLen - i;
+ }
+ if (pVNC->ublen + portionLen > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ memcpy(&pVNC->updateBuf[pVNC->ublen], &tightAfterBuf[i], portionLen);
+ pVNC->ublen += portionLen;
+ }
+ cl->rfbBytesSent[rfbEncodingTight] += compressedLen;
+ return TRUE;
+}
+
+/*
+ * Code to determine how many different colors used in rectangle.
+ */
+
+static void
+FillPalette8(count)
+ int count;
+{
+ CARD8 *data = (CARD8 *)tightBeforeBuf;
+ CARD8 c0, c1;
+ int i, n0, n1;
+
+ paletteNumColors = 0;
+
+ c0 = data[0];
+ for (i = 1; i < count && data[i] == c0; i++);
+ if (i == count) {
+ paletteNumColors = 1;
+ return; /* Solid rectangle */
+ }
+
+ if (paletteMaxColors < 2)
+ return;
+
+ n0 = i;
+ c1 = data[i];
+ n1 = 0;
+ for (i++; i < count; i++) {
+ if (data[i] == c0) {
+ n0++;
+ } else if (data[i] == c1) {
+ n1++;
+ } else
+ break;
+ }
+ if (i == count) {
+ if (n0 > n1) {
+ monoBackground = (CARD32)c0;
+ monoForeground = (CARD32)c1;
+ } else {
+ monoBackground = (CARD32)c1;
+ monoForeground = (CARD32)c0;
+ }
+ paletteNumColors = 2; /* Two colors */
+ }
+}
+
+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \
+ \
+static void \
+FillPalette##bpp(count) \
+ int count; \
+{ \
+ CARD##bpp *data = (CARD##bpp *)tightBeforeBuf; \
+ CARD##bpp c0, c1, ci = 0; \
+ int i, n0, n1, ni; \
+ \
+ c0 = data[0]; \
+ for (i = 1; i < count && data[i] == c0; i++); \
+ if (i >= count) { \
+ paletteNumColors = 1; /* Solid rectangle */ \
+ return; \
+ } \
+ \
+ if (paletteMaxColors < 2) { \
+ paletteNumColors = 0; /* Full-color encoding preferred */ \
+ return; \
+ } \
+ \
+ n0 = i; \
+ c1 = data[i]; \
+ n1 = 0; \
+ for (i++; i < count; i++) { \
+ ci = data[i]; \
+ if (ci == c0) { \
+ n0++; \
+ } else if (ci == c1) { \
+ n1++; \
+ } else \
+ break; \
+ } \
+ if (i >= count) { \
+ if (n0 > n1) { \
+ monoBackground = (CARD32)c0; \
+ monoForeground = (CARD32)c1; \
+ } else { \
+ monoBackground = (CARD32)c1; \
+ monoForeground = (CARD32)c0; \
+ } \
+ paletteNumColors = 2; /* Two colors */ \
+ return; \
+ } \
+ \
+ PaletteReset(); \
+ PaletteInsert (c0, (CARD32)n0, bpp); \
+ PaletteInsert (c1, (CARD32)n1, bpp); \
+ \
+ ni = 1; \
+ for (i++; i < count; i++) { \
+ if (data[i] == ci) { \
+ ni++; \
+ } else { \
+ if (!PaletteInsert (ci, (CARD32)ni, bpp)) \
+ return; \
+ ci = data[i]; \
+ ni = 1; \
+ } \
+ } \
+ PaletteInsert (ci, (CARD32)ni, bpp); \
+}
+
+DEFINE_FILL_PALETTE_FUNCTION(16)
+DEFINE_FILL_PALETTE_FUNCTION(32)
+
+
+/*
+ * Functions to operate with palette structures.
+ */
+
+#define HASH_FUNC16(rgb) ((int)((((rgb) >> 8) + (rgb)) & 0xFF))
+#define HASH_FUNC32(rgb) ((int)((((rgb) >> 16) + ((rgb) >> 8)) & 0xFF))
+
+static void
+PaletteReset(void)
+{
+ paletteNumColors = 0;
+ memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *));
+}
+
+static int
+PaletteInsert(CARD32 rgb, int numPixels, int bpp)
+{
+ COLOR_LIST *pnode;
+ COLOR_LIST *prev_pnode = NULL;
+ int hash_key, idx, new_idx, count;
+
+ hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb);
+
+ pnode = palette.hash[hash_key];
+
+ while (pnode != NULL) {
+ if (pnode->rgb == rgb) {
+ /* Such palette entry already exists. */
+ new_idx = idx = pnode->idx;
+ count = palette.entry[idx].numPixels + numPixels;
+ if (new_idx && palette.entry[new_idx-1].numPixels < count) {
+ do {
+ palette.entry[new_idx] = palette.entry[new_idx-1];
+ palette.entry[new_idx].listNode->idx = new_idx;
+ new_idx--;
+ }
+ while (new_idx && palette.entry[new_idx-1].numPixels < count);
+ palette.entry[new_idx].listNode = pnode;
+ pnode->idx = new_idx;
+ }
+ palette.entry[new_idx].numPixels = count;
+ return paletteNumColors;
+ }
+ prev_pnode = pnode;
+ pnode = pnode->next;
+ }
+
+ /* Check if palette is full. */
+ if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) {
+ paletteNumColors = 0;
+ return 0;
+ }
+
+ /* Move palette entries with lesser pixel counts. */
+ for ( idx = paletteNumColors;
+ idx > 0 && palette.entry[idx-1].numPixels < numPixels;
+ idx-- ) {
+ palette.entry[idx] = palette.entry[idx-1];
+ palette.entry[idx].listNode->idx = idx;
+ }
+
+ /* Add new palette entry into the freed slot. */
+ pnode = &palette.list[paletteNumColors];
+ if (prev_pnode != NULL) {
+ prev_pnode->next = pnode;
+ } else {
+ palette.hash[hash_key] = pnode;
+ }
+ pnode->next = NULL;
+ pnode->idx = idx;
+ pnode->rgb = rgb;
+ palette.entry[idx].listNode = pnode;
+ palette.entry[idx].numPixels = numPixels;
+
+ return (++paletteNumColors);
+}
+
+
+/*
+ * Converting 32-bit color samples into 24-bit colors.
+ * Should be called only when redMax, greenMax and blueMax are 255.
+ * Color components assumed to be byte-aligned.
+ */
+
+static void Pack24(pScreen, buf, fmt, count)
+ ScreenPtr pScreen;
+ unsigned char *buf;
+ rfbPixelFormat *fmt;
+ int count;
+{
+ VNCSCREENPTR(pScreen);
+ CARD32 *buf32;
+ CARD32 pix;
+ int r_shift, g_shift, b_shift;
+
+ buf32 = (CARD32 *)buf;
+
+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) {
+ r_shift = fmt->redShift;
+ g_shift = fmt->greenShift;
+ b_shift = fmt->blueShift;
+ } else {
+ r_shift = 24 - fmt->redShift;
+ g_shift = 24 - fmt->greenShift;
+ b_shift = 24 - fmt->blueShift;
+ }
+
+ while (count--) {
+ pix = *buf32++;
+ *buf++ = (char)(pix >> r_shift);
+ *buf++ = (char)(pix >> g_shift);
+ *buf++ = (char)(pix >> b_shift);
+ }
+}
+
+
+/*
+ * Converting truecolor samples into palette indices.
+ */
+
+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \
+ \
+static void \
+EncodeIndexedRect##bpp(buf, count) \
+ CARD8 *buf; \
+ int count; \
+{ \
+ COLOR_LIST *pnode; \
+ CARD##bpp *src; \
+ CARD##bpp rgb; \
+ int rep = 0; \
+ \
+ src = (CARD##bpp *) buf; \
+ \
+ while (count--) { \
+ rgb = *src++; \
+ while (count && *src == rgb) { \
+ rep++, src++, count--; \
+ } \
+ pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \
+ while (pnode != NULL) { \
+ if ((CARD##bpp)pnode->rgb == rgb) { \
+ *buf++ = (CARD8)pnode->idx; \
+ while (rep) { \
+ *buf++ = (CARD8)pnode->idx; \
+ rep--; \
+ } \
+ break; \
+ } \
+ pnode = pnode->next; \
+ } \
+ } \
+}
+
+DEFINE_IDX_ENCODE_FUNCTION(16)
+DEFINE_IDX_ENCODE_FUNCTION(32)
+
+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \
+ \
+static void \
+EncodeMonoRect##bpp(buf, w, h) \
+ CARD8 *buf; \
+ int w, h; \
+{ \
+ CARD##bpp *ptr; \
+ CARD##bpp bg; \
+ unsigned int value, mask; \
+ int aligned_width; \
+ int x, y, bg_bits; \
+ \
+ ptr = (CARD##bpp *) buf; \
+ bg = (CARD##bpp) monoBackground; \
+ aligned_width = w - w % 8; \
+ \
+ for (y = 0; y < h; y++) { \
+ for (x = 0; x < aligned_width; x += 8) { \
+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \
+ if (*ptr++ != bg) \
+ break; \
+ } \
+ if (bg_bits == 8) { \
+ *buf++ = 0; \
+ continue; \
+ } \
+ mask = 0x80 >> bg_bits; \
+ value = mask; \
+ for (bg_bits++; bg_bits < 8; bg_bits++) { \
+ mask >>= 1; \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ } \
+ *buf++ = (CARD8)value; \
+ } \
+ \
+ mask = 0x80; \
+ value = 0; \
+ if (x >= w) \
+ continue; \
+ \
+ for (; x < w; x++) { \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ mask >>= 1; \
+ } \
+ *buf++ = (CARD8)value; \
+ } \
+}
+
+DEFINE_MONO_ENCODE_FUNCTION(8)
+DEFINE_MONO_ENCODE_FUNCTION(16)
+DEFINE_MONO_ENCODE_FUNCTION(32)
+
+
+/*
+ * ``Gradient'' filter for 24-bit color samples.
+ * Should be called only when redMax, greenMax and blueMax are 255.
+ * Color components assumed to be byte-aligned.
+ */
+
+static void
+FilterGradient24(pScreen, buf, fmt, w, h)
+ ScreenPtr pScreen;
+ unsigned char *buf;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ VNCSCREENPTR(pScreen);
+ CARD32 *buf32;
+ CARD32 pix32;
+ int *prevRowPtr;
+ int shiftBits[3];
+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3];
+ int prediction;
+ int x, y, c;
+
+ buf32 = (CARD32 *)buf;
+ memset (prevRowBuf, 0, w * 3 * sizeof(int));
+
+ if (!pVNC->rfbServerFormat.bigEndian == !fmt->bigEndian) {
+ shiftBits[0] = fmt->redShift;
+ shiftBits[1] = fmt->greenShift;
+ shiftBits[2] = fmt->blueShift;
+ } else {
+ shiftBits[0] = 24 - fmt->redShift;
+ shiftBits[1] = 24 - fmt->greenShift;
+ shiftBits[2] = 24 - fmt->blueShift;
+ }
+
+ for (y = 0; y < h; y++) {
+ for (c = 0; c < 3; c++) {
+ pixUpper[c] = 0;
+ pixHere[c] = 0;
+ }
+ prevRowPtr = prevRowBuf;
+ for (x = 0; x < w; x++) {
+ pix32 = *buf32++;
+ for (c = 0; c < 3; c++) {
+ pixUpperLeft[c] = pixUpper[c];
+ pixLeft[c] = pixHere[c];
+ pixUpper[c] = *prevRowPtr;
+ pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF);
+ *prevRowPtr++ = pixHere[c];
+
+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c];
+ if (prediction < 0) {
+ prediction = 0;
+ } else if (prediction > 0xFF) {
+ prediction = 0xFF;
+ }
+ *buf++ = (char)(pixHere[c] - prediction);
+ }
+ }
+ }
+}
+
+
+/*
+ * ``Gradient'' filter for other color depths.
+ */
+
+#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \
+ \
+static void \
+FilterGradient##bpp(pScreen, buf, fmt, w, h) \
+ ScreenPtr pScreen; \
+ CARD##bpp *buf; \
+ rfbPixelFormat *fmt; \
+ int w, h; \
+{ \
+ VNCSCREENPTR(pScreen); \
+ CARD##bpp pix, diff; \
+ Bool endianMismatch; \
+ int *prevRowPtr; \
+ int maxColor[3], shiftBits[3]; \
+ int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \
+ int prediction; \
+ int x, y, c; \
+ \
+ memset (prevRowBuf, 0, w * 3 * sizeof(int)); \
+ \
+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \
+ \
+ maxColor[0] = fmt->redMax; \
+ maxColor[1] = fmt->greenMax; \
+ maxColor[2] = fmt->blueMax; \
+ shiftBits[0] = fmt->redShift; \
+ shiftBits[1] = fmt->greenShift; \
+ shiftBits[2] = fmt->blueShift; \
+ \
+ for (y = 0; y < h; y++) { \
+ for (c = 0; c < 3; c++) { \
+ pixUpper[c] = 0; \
+ pixHere[c] = 0; \
+ } \
+ prevRowPtr = prevRowBuf; \
+ for (x = 0; x < w; x++) { \
+ pix = *buf; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ diff = 0; \
+ for (c = 0; c < 3; c++) { \
+ pixUpperLeft[c] = pixUpper[c]; \
+ pixLeft[c] = pixHere[c]; \
+ pixUpper[c] = *prevRowPtr; \
+ pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ *prevRowPtr++ = pixHere[c]; \
+ \
+ prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \
+ if (prediction < 0) { \
+ prediction = 0; \
+ } else if (prediction > maxColor[c]) { \
+ prediction = maxColor[c]; \
+ } \
+ diff |= ((pixHere[c] - prediction) & maxColor[c]) \
+ << shiftBits[c]; \
+ } \
+ if (endianMismatch) { \
+ diff = Swap##bpp(diff); \
+ } \
+ *buf++ = diff; \
+ } \
+ } \
+}
+
+DEFINE_GRADIENT_FILTER_FUNCTION(16)
+DEFINE_GRADIENT_FILTER_FUNCTION(32)
+
+
+/*
+ * Code to guess if given rectangle is suitable for smooth image
+ * compression (by applying "gradient" filter or JPEG coder).
+ */
+
+#define JPEG_MIN_RECT_SIZE 4096
+
+#define DETECT_SUBROW_WIDTH 7
+#define DETECT_MIN_WIDTH 8
+#define DETECT_MIN_HEIGHT 8
+
+static int
+DetectSmoothImage (cl, fmt, w, h)
+ rfbClientPtr cl;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ unsigned long avgError;
+
+ if ( pVNC->rfbServerFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 ||
+ w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) {
+ return 0;
+ }
+
+ if (cl->tightQualityLevel != -1) {
+ if (w * h < JPEG_MIN_RECT_SIZE) {
+ return 0;
+ }
+ } else {
+ if ( rfbTightDisableGradient ||
+ w * h < tightConf[cl->tightCompressLevel].gradientMinRectSize ) {
+ return 0;
+ }
+ }
+
+ if (fmt->bitsPerPixel == 32) {
+ if (usePixelFormat24) {
+ avgError = DetectSmoothImage24(cl, fmt, w, h);
+ if (cl->tightQualityLevel != -1) {
+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold24);
+ }
+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold24);
+ } else {
+ avgError = DetectSmoothImage32(cl, fmt, w, h);
+ }
+ } else {
+ avgError = DetectSmoothImage16(cl, fmt, w, h);
+ }
+ if (cl->tightQualityLevel != -1) {
+ return (avgError < tightConf[cl->tightQualityLevel].jpegThreshold);
+ }
+ return (avgError < tightConf[cl->tightCompressLevel].gradientThreshold);
+}
+
+static unsigned long
+DetectSmoothImage24 (cl, fmt, w, h)
+ rfbClientPtr cl;
+ rfbPixelFormat *fmt;
+ int w, h;
+{
+ int off;
+ int x, y, d, dx, c;
+ int diffStat[256];
+ int pixelCount = 0;
+ int pix, left[3];
+ unsigned long avgError;
+
+ /* If client is big-endian, color samples begin from the second
+ byte (offset 1) of a 32-bit pixel value. */
+ off = (fmt->bigEndian != 0);
+
+ memset(diffStat, 0, 256*sizeof(int));
+
+ y = 0, x = 0;
+ while (y < h && x < w) {
+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) {
+ for (c = 0; c < 3; c++) {
+ left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF;
+ }
+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) {
+ for (c = 0; c < 3; c++) {
+ pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF;
+ diffStat[abs(pix - left[c])]++;
+ left[c] = pix;
+ }
+ pixelCount++;
+ }
+ }
+ if (w > h) {
+ x += h;
+ y = 0;
+ } else {
+ x = 0;
+ y += w;
+ }
+ }
+
+ if (diffStat[0] * 33 / pixelCount >= 95)
+ return 0;
+
+ avgError = 0;
+ for (c = 1; c < 8; c++) {
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c);
+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2)
+ return 0;
+ }
+ for (; c < 256; c++) {
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c);
+ }
+ avgError /= (pixelCount * 3 - diffStat[0]);
+
+ return avgError;
+}
+
+#define DEFINE_DETECT_FUNCTION(bpp) \
+ \
+static unsigned long \
+DetectSmoothImage##bpp (cl, fmt, w, h) \
+ rfbClientPtr cl; \
+ rfbPixelFormat *fmt; \
+ int w, h; \
+{ \
+ VNCSCREENPTR(cl->pScreen); \
+ Bool endianMismatch; \
+ CARD##bpp pix; \
+ int maxColor[3], shiftBits[3]; \
+ int x, y, d, dx, c; \
+ int diffStat[256]; \
+ int pixelCount = 0; \
+ int sample, sum, left[3]; \
+ unsigned long avgError; \
+ \
+ endianMismatch = (!pVNC->rfbServerFormat.bigEndian != !fmt->bigEndian); \
+ \
+ maxColor[0] = fmt->redMax; \
+ maxColor[1] = fmt->greenMax; \
+ maxColor[2] = fmt->blueMax; \
+ shiftBits[0] = fmt->redShift; \
+ shiftBits[1] = fmt->greenShift; \
+ shiftBits[2] = fmt->blueShift; \
+ \
+ memset(diffStat, 0, 256*sizeof(int)); \
+ \
+ y = 0, x = 0; \
+ while (y < h && x < w) { \
+ for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \
+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d]; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ for (c = 0; c < 3; c++) { \
+ left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ } \
+ for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \
+ pix = ((CARD##bpp *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \
+ if (endianMismatch) { \
+ pix = Swap##bpp(pix); \
+ } \
+ sum = 0; \
+ for (c = 0; c < 3; c++) { \
+ sample = (int)(pix >> shiftBits[c] & maxColor[c]); \
+ sum += abs(sample - left[c]); \
+ left[c] = sample; \
+ } \
+ if (sum > 255) \
+ sum = 255; \
+ diffStat[sum]++; \
+ pixelCount++; \
+ } \
+ } \
+ if (w > h) { \
+ x += h; \
+ y = 0; \
+ } else { \
+ x = 0; \
+ y += w; \
+ } \
+ } \
+ \
+ if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \
+ return 0; \
+ \
+ avgError = 0; \
+ for (c = 1; c < 8; c++) { \
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \
+ if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \
+ return 0; \
+ } \
+ for (; c < 256; c++) { \
+ avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \
+ } \
+ avgError /= (pixelCount - diffStat[0]); \
+ \
+ return avgError; \
+}
+
+DEFINE_DETECT_FUNCTION(16)
+DEFINE_DETECT_FUNCTION(32)
+
+
+/*
+ * JPEG compression stuff.
+ */
+
+static struct jpeg_destination_mgr jpegDstManager;
+static Bool jpegError;
+static int jpegDstDataLen;
+
+/**
+ * Send the given image rect with jpeg compression.
+ * \param buffer the source image buffer
+ * \param w width of source image in pixels
+ * \param h height of source image in pixels
+ * \param quality jpeg enoding quality
+ */
+static Bool
+SendJpegRect(rfbClientPtr cl, const CARD8 *buffer, int w, int h,
+ int quality)
+{
+ VNCSCREENPTR(cl->pScreen);
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ CARD8 *srcBuf;
+ JSAMPROW rowPointer[1];
+ int i;
+
+ if (pVNC->rfbServerFormat.bitsPerPixel == 8)
+ return SendFullColorRect(cl, w, h);
+
+ srcBuf = (CARD8 *)xalloc(w * 3);
+ if (srcBuf == NULL) {
+ return SendFullColorRect(cl, w, h);
+ }
+ 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, quality, TRUE);
+
+ JpegSetDstManager (&cinfo);
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ for (i = 0; i < h; i++) {
+ PrepareRowForJpeg(cl->pScreen, srcBuf, buffer, i, w);
+ jpeg_write_scanlines(&cinfo, rowPointer, 1);
+ if (jpegError)
+ break;
+ }
+
+ if (!jpegError)
+ jpeg_finish_compress(&cinfo);
+
+ jpeg_destroy_compress(&cinfo);
+ xfree((char *)srcBuf);
+
+ if (jpegError)
+ return SendFullColorRect(cl, w, h);
+
+ if (pVNC->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ pVNC->updateBuf[pVNC->ublen++] = (char)(rfbTightJpeg << 4);
+ cl->rfbBytesSent[rfbEncodingTight]++;
+
+ return SendCompressedData(cl, jpegDstDataLen);
+}
+
+/**
+ * Convert pixel data to format needed for jpeg library.
+ * \dst destination buffer (24bpp)
+ * \buffer source buffer (16 or 32bpp)
+ * \row which image row to prepare/convert
+ * \width width of source buffer, in pixels
+ */
+static void
+PrepareRowForJpeg(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer,
+ int row, int width)
+{
+ VNCSCREENPTR(pScreen);
+ if (pVNC->rfbServerFormat.bitsPerPixel == 32) {
+ if ( pVNC->rfbServerFormat.redMax == 0xFF &&
+ pVNC->rfbServerFormat.greenMax == 0xFF &&
+ pVNC->rfbServerFormat.blueMax == 0xFF ) {
+ PrepareRowForJpeg24(pScreen, dst, buffer, row, width);
+ } else {
+ PrepareRowForJpeg32(pScreen, dst, buffer, row, width);
+ }
+ } else {
+ /* 16 bpp assumed. */
+ PrepareRowForJpeg16(pScreen, dst, buffer, row, width);
+ }
+}
+
+/**
+ * Src buffer is 32bpp, dst buffer is 24bpp (optimized case).
+ */
+static void
+PrepareRowForJpeg24(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer,
+ int row, int width)
+{
+ VNCSCREENPTR(pScreen);
+ const CARD32 *src = ((const CARD32 *) buffer) + row * width;
+ while (width--) {
+ CARD32 pix = *src++;
+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.redShift);
+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.greenShift);
+ *dst++ = (CARD8)(pix >> pVNC->rfbServerFormat.blueShift);
+ }
+}
+
+/**
+ * PrepareRowForJpeg16/32: convert 16bpp or 32bpp pixels to 24bpp
+ */
+#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \
+ \
+static void \
+PrepareRowForJpeg##bpp(ScreenPtr pScreen, CARD8 *dst, const CARD8 *buffer, \
+ int row, int width) \
+{ \
+ VNCSCREENPTR(pScreen); \
+ CARD##bpp *fbptr; \
+ CARD##bpp pix; \
+ int inRed, inGreen, inBlue; \
+ \
+ fbptr = ((CARD##bpp *) buffer) + row * width; \
+ \
+ while (width--) { \
+ pix = *fbptr++; \
+ \
+ inRed = (int) \
+ (pix >> pVNC->rfbServerFormat.redShift & pVNC->rfbServerFormat.redMax); \
+ inGreen = (int) \
+ (pix >> pVNC->rfbServerFormat.greenShift & pVNC->rfbServerFormat.greenMax); \
+ inBlue = (int) \
+ (pix >> pVNC->rfbServerFormat.blueShift & pVNC->rfbServerFormat.blueMax); \
+ \
+ *dst++ = (CARD8)((inRed * 255 + pVNC->rfbServerFormat.redMax / 2) / \
+ pVNC->rfbServerFormat.redMax); \
+ *dst++ = (CARD8)((inGreen * 255 + pVNC->rfbServerFormat.greenMax / 2) / \
+ pVNC->rfbServerFormat.greenMax); \
+ *dst++ = (CARD8)((inBlue * 255 + pVNC->rfbServerFormat.blueMax / 2) / \
+ pVNC->rfbServerFormat.blueMax); \
+ } \
+}
+
+DEFINE_JPEG_GET_ROW_FUNCTION(16)
+DEFINE_JPEG_GET_ROW_FUNCTION(32)
+
+/*
+ * Destination manager implementation for JPEG library.
+ */
+
+static void
+JpegInitDestination(j_compress_ptr cinfo)
+{
+ jpegError = FALSE;
+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf;
+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize;
+}
+
+static boolean
+JpegEmptyOutputBuffer(j_compress_ptr cinfo)
+{
+ jpegError = TRUE;
+ jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf;
+ jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize;
+
+ return TRUE;
+}
+
+static void
+JpegTermDestination(j_compress_ptr cinfo)
+{
+ jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer;
+}
+
+static void
+JpegSetDstManager(j_compress_ptr cinfo)
+{
+ jpegDstManager.init_destination = JpegInitDestination;
+ jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer;
+ jpegDstManager.term_destination = JpegTermDestination;
+ cinfo->dest = &jpegDstManager;
+}
+
--- xorg-server-1.7.4/hw/vnc/translate.c
+++ xorg-server-1.7.4/hw/vnc/translate.c
@@ -0,0 +1,502 @@
+/*
+ * translate.c - translate between different pixel formats
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include "rfb.h"
+#if XFREE86VNC
+#include <micmap.h>
+#endif
+
+static void PrintPixelFormat(rfbPixelFormat *pf);
+static Bool rfbSetClientColourMapBGR233(rfbClientPtr cl);
+
+Bool rfbEconomicTranslate = FALSE;
+
+/*
+ * Some standard pixel formats.
+ */
+
+static const rfbPixelFormat BGR233Format = {
+ 8, 8, 0, 1, 7, 7, 3, 0, 3, 6
+};
+
+
+/*
+ * Macro to compare pixel formats.
+ */
+
+#define PF_EQ(x,y) \
+ ((x.bitsPerPixel == y.bitsPerPixel) && \
+ (x.depth == y.depth) && \
+ ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \
+ (x.trueColour == y.trueColour) && \
+ (!x.trueColour || ((x.redMax == y.redMax) && \
+ (x.greenMax == y.greenMax) && \
+ (x.blueMax == y.blueMax) && \
+ (x.redShift == y.redShift) && \
+ (x.greenShift == y.greenShift) && \
+ (x.blueShift == y.blueShift))))
+
+#define CONCAT2(a,b) a##b
+#define CONCAT2E(a,b) CONCAT2(a,b)
+#define CONCAT4(a,b,c,d) a##b##c##d
+#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)
+
+#define OUT 8
+#include "tableinittctemplate.c"
+#include "tableinitcmtemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+#define OUT 16
+#include "tableinittctemplate.c"
+#include "tableinitcmtemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+#define OUT 32
+#include "tableinittctemplate.c"
+#include "tableinitcmtemplate.c"
+#define IN 8
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 16
+#include "tabletranstemplate.c"
+#undef IN
+#define IN 32
+#include "tabletranstemplate.c"
+#undef IN
+#undef OUT
+
+typedef void (*rfbInitTableFnType)(ScreenPtr pScreen, char **table, rfbPixelFormat *in,
+ rfbPixelFormat *out);
+
+rfbInitTableFnType rfbInitTrueColourSingleTableFns[3] = {
+ rfbInitTrueColourSingleTable8,
+ rfbInitTrueColourSingleTable16,
+ rfbInitTrueColourSingleTable32
+};
+
+rfbInitTableFnType rfbInitColourMapSingleTableFns[3] = {
+ rfbInitColourMapSingleTable8,
+ rfbInitColourMapSingleTable16,
+ rfbInitColourMapSingleTable32
+};
+
+rfbInitTableFnType rfbInitTrueColourRGBTablesFns[3] = {
+ rfbInitTrueColourRGBTables8,
+ rfbInitTrueColourRGBTables16,
+ rfbInitTrueColourRGBTables32
+};
+
+rfbTranslateFnType rfbTranslateWithSingleTableFns[3][3] = {
+ { rfbTranslateWithSingleTable8to8,
+ rfbTranslateWithSingleTable8to16,
+ rfbTranslateWithSingleTable8to32 },
+ { rfbTranslateWithSingleTable16to8,
+ rfbTranslateWithSingleTable16to16,
+ rfbTranslateWithSingleTable16to32 },
+ { rfbTranslateWithSingleTable32to8,
+ rfbTranslateWithSingleTable32to16,
+ rfbTranslateWithSingleTable32to32 }
+};
+
+rfbTranslateFnType rfbTranslateWithRGBTablesFns[3][3] = {
+ { rfbTranslateWithRGBTables8to8,
+ rfbTranslateWithRGBTables8to16,
+ rfbTranslateWithRGBTables8to32 },
+ { rfbTranslateWithRGBTables16to8,
+ rfbTranslateWithRGBTables16to16,
+ rfbTranslateWithRGBTables16to32 },
+ { rfbTranslateWithRGBTables32to8,
+ rfbTranslateWithRGBTables32to16,
+ rfbTranslateWithRGBTables32to32 }
+};
+
+
+
+/*
+ * rfbTranslateNone is used when no translation is required.
+ */
+
+void
+rfbTranslateNone(ScreenPtr pScreen, char *table, rfbPixelFormat *in, rfbPixelFormat *out,
+ unsigned char *optr, int bytesBetweenInputLines,
+ int width, int height, int x, int y)
+{
+ VNCSCREENPTR(pScreen);
+ DrawablePtr pDraw = (DrawablePtr)WindowTable[pScreen->myNum];
+ int truewidth = PixmapBytePad(width, in->bitsPerPixel) / 4;
+
+ if ((x + truewidth > pVNC->width) || truewidth != width) {
+ unsigned char *buffer = malloc(truewidth * height * in->bitsPerPixel / 8);
+ unsigned char *buf = buffer;
+
+ (*pScreen->GetImage)(pDraw, x, y, truewidth, height, ZPixmap, ~0, (char*)buf);
+ while (height--) {
+ memcpy(optr, buf, width * in->bitsPerPixel / 8);
+ optr += width * in->bitsPerPixel / 8;
+ buf += truewidth * in->bitsPerPixel / 8;
+ }
+ free(buffer);
+ return;
+ }
+
+ (*pScreen->GetImage)(pDraw, x, y, width, height, ZPixmap, ~0, (char*)optr);
+}
+
+
+/*
+ * rfbSetTranslateFunction sets the translation function.
+ */
+
+Bool
+rfbSetTranslateFunction(cl)
+ rfbClientPtr cl;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbLog("Pixel format for client %s:\n",cl->host);
+ PrintPixelFormat(&cl->format);
+
+ /*
+ * Check that bits per pixel values are valid
+ */
+
+ if ((pVNC->rfbServerFormat.bitsPerPixel != 8) &&
+ (pVNC->rfbServerFormat.bitsPerPixel != 16) &&
+ (pVNC->rfbServerFormat.bitsPerPixel != 32))
+ {
+ rfbLog("%s: server bits per pixel not 8, 16 or 32\n",
+ "rfbSetTranslateFunction");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ if ((cl->format.bitsPerPixel != 8) &&
+ (cl->format.bitsPerPixel != 16) &&
+ (cl->format.bitsPerPixel != 32))
+ {
+ rfbLog("%s: client bits per pixel not 8, 16 or 32\n",
+ "rfbSetTranslateFunction");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ if (!pVNC->rfbServerFormat.trueColour &&
+ (pVNC->rfbServerFormat.bitsPerPixel != 8) &&
+#if XFREE86VNC
+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) {
+#else
+ (pVNC->rfbInstalledColormap->class == PseudoColor)) {
+#endif
+ rfbLog("rfbSetTranslateFunction: server has colour map "
+ "but %d-bit - can only cope with 8-bit colour maps\n",
+ pVNC->rfbServerFormat.bitsPerPixel);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ if (!cl->format.trueColour &&
+ (cl->format.bitsPerPixel != 8) &&
+#if XFREE86VNC
+ (miInstalledMaps[cl->pScreen->myNum]->class == PseudoColor)) {
+#else
+ (pVNC->rfbInstalledColormap->class == PseudoColor) ) {
+#endif
+ rfbLog("rfbSetTranslateFunction: client has colour map "
+ "but %d-bit - can only cope with 8-bit colour maps\n",
+ cl->format.bitsPerPixel);
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ /*
+ * bpp is valid, now work out how to translate
+ */
+
+ if (!cl->format.trueColour) {
+
+ /* ? -> colour map */
+
+ if (!pVNC->rfbServerFormat.trueColour) {
+
+ /* colour map -> colour map */
+
+#if XFREE86VNC
+ if (miInstalledMaps[cl->pScreen->myNum]->class == DirectColor) {
+#else
+ if (pVNC->rfbInstalledColormap->class == DirectColor) {
+#endif
+ rfbLog("rfbSetTranslateFunction: client is %d-bit DirectColor,"
+ " client has colour map\n",cl->format.bitsPerPixel);
+
+ cl->translateFn = rfbTranslateWithRGBTablesFns
+ [pVNC->rfbServerFormat.bitsPerPixel / 16]
+ [cl->format.bitsPerPixel / 16];
+
+ (*rfbInitTrueColourRGBTablesFns [cl->format.bitsPerPixel / 16])
+ (cl->pScreen, &cl->translateLookupTable,
+ &pVNC->rfbServerFormat, &cl->format);
+
+ return rfbSetClientColourMap(cl, 0, 0);
+
+ /* PseudoColor colormap */
+
+ } else {
+ rfbLog("rfbSetTranslateFunction: both 8-bit colour map: "
+ "no translation needed\n");
+ cl->translateFn = rfbTranslateNone;
+ return rfbSetClientColourMap(cl, 0, 0);
+ }
+ }
+
+ /*
+ * truecolour -> colour map
+ *
+ * Set client's colour map to BGR233, then effectively it's
+ * truecolour as well
+ */
+
+ if (!rfbSetClientColourMapBGR233(cl))
+ return FALSE;
+
+ cl->format = BGR233Format;
+ }
+
+ /* ? -> truecolour */
+
+ if (!pVNC->rfbServerFormat.trueColour) {
+
+ /* colour map -> truecolour */
+
+ rfbLog("rfbSetTranslateFunction: client is %d-bit trueColour,"
+ " server has colour map\n",cl->format.bitsPerPixel);
+
+ cl->translateFn = rfbTranslateWithSingleTableFns
+ [pVNC->rfbServerFormat.bitsPerPixel / 16]
+ [cl->format.bitsPerPixel / 16];
+
+ return rfbSetClientColourMap(cl, 0, 0);
+ }
+
+ /* truecolour -> truecolour */
+
+ if (PF_EQ(cl->format,pVNC->rfbServerFormat)) {
+
+ /* client & server the same */
+
+ rfbLog(" no translation needed\n");
+ cl->translateFn = rfbTranslateNone;
+ return TRUE;
+ }
+
+ if ((pVNC->rfbServerFormat.bitsPerPixel < 16) ||
+ (!rfbEconomicTranslate && (pVNC->rfbServerFormat.bitsPerPixel == 16))) {
+
+ /* we can use a single lookup table for <= 16 bpp */
+
+ cl->translateFn = rfbTranslateWithSingleTableFns
+ [pVNC->rfbServerFormat.bitsPerPixel / 16]
+ [cl->format.bitsPerPixel / 16];
+
+ (*rfbInitTrueColourSingleTableFns
+ [cl->format.bitsPerPixel / 16]) (cl->pScreen,
+ &cl->translateLookupTable,
+ &pVNC->rfbServerFormat, &cl->format);
+
+ } else {
+
+ /* otherwise we use three separate tables for red, green and blue */
+
+ cl->translateFn = rfbTranslateWithRGBTablesFns
+ [pVNC->rfbServerFormat.bitsPerPixel / 16]
+ [cl->format.bitsPerPixel / 16];
+
+ (*rfbInitTrueColourRGBTablesFns
+ [cl->format.bitsPerPixel / 16]) (cl->pScreen,
+ &cl->translateLookupTable,
+ &pVNC->rfbServerFormat, &cl->format);
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * rfbSetClientColourMapBGR233 sets the client's colour map so that it's
+ * just like an 8-bit BGR233 true colour client.
+ */
+
+static Bool
+rfbSetClientColourMapBGR233(rfbClientPtr cl)
+{
+ char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
+ rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
+ CARD16 *rgb = (CARD16 *)(&buf[sz_rfbSetColourMapEntriesMsg]);
+ int i, len;
+ int r, g, b;
+
+ if (cl->format.bitsPerPixel != 8) {
+ rfbLog("%s: client not 8 bits per pixel\n",
+ "rfbSetClientColourMapBGR233");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+
+ scme->type = rfbSetColourMapEntries;
+
+ scme->firstColour = Swap16IfLE(0);
+ scme->nColours = Swap16IfLE(256);
+
+ len = sz_rfbSetColourMapEntriesMsg;
+
+ i = 0;
+
+ for (b = 0; b < 4; b++) {
+ for (g = 0; g < 8; g++) {
+ for (r = 0; r < 8; r++) {
+ rgb[i++] = Swap16IfLE(r * 65535 / 7);
+ rgb[i++] = Swap16IfLE(g * 65535 / 7);
+ rgb[i++] = Swap16IfLE(b * 65535 / 3);
+ }
+ }
+ }
+
+ len += 256 * 3 * 2;
+
+ if (WriteExact(cl->sock, buf, len) < 0) {
+ rfbLogPerror("rfbSetClientColourMapBGR233: write");
+ rfbCloseSock(cl->pScreen, cl->sock);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*
+ * rfbSetClientColourMap is called to set the client's colour map. If the
+ * client is a true colour client, we simply update our own translation table
+ * and mark the whole screen as having been modified.
+ */
+
+Bool
+rfbSetClientColourMap(cl, firstColour, nColours)
+ rfbClientPtr cl;
+ int firstColour;
+ int nColours;
+{
+ VNCSCREENPTR(cl->pScreen);
+ BoxRec box;
+
+ if (nColours == 0) {
+#if XFREE86VNC
+ nColours = miInstalledMaps[cl->pScreen->myNum]->pVisual->ColormapEntries;
+#else
+ nColours = pVNC->rfbInstalledColormap->pVisual->ColormapEntries;
+#endif
+ }
+
+ if (pVNC->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) {
+ return TRUE;
+ }
+
+ if (cl->format.trueColour) {
+ (*rfbInitColourMapSingleTableFns
+ [cl->format.bitsPerPixel / 16]) (cl->pScreen,
+ &cl->translateLookupTable,
+ &pVNC->rfbServerFormat, &cl->format);
+
+ REGION_UNINIT(cl->pScreen,&cl->modifiedRegion);
+ box.x1 = box.y1 = 0;
+ box.x2 = pVNC->width;
+ box.y2 = pVNC->height;
+ REGION_INIT(cl->pScreen,&cl->modifiedRegion,&box,0);
+
+ return TRUE;
+ }
+
+ return rfbSendSetColourMapEntries(cl, firstColour, nColours);
+}
+
+
+/*
+ * rfbSetClientColourMaps sets the colour map for each RFB client.
+ */
+
+void
+rfbSetClientColourMaps(firstColour, nColours)
+ int firstColour;
+ int nColours;
+{
+ rfbClientPtr cl, nextCl;
+
+ for (cl = rfbClientHead; cl; cl = nextCl) {
+ nextCl = cl->next;
+ rfbSetClientColourMap(cl, firstColour, nColours);
+ }
+}
+
+
+static void
+PrintPixelFormat(pf)
+ rfbPixelFormat *pf;
+{
+ if (pf->bitsPerPixel == 1) {
+ rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n",
+ (pf->bigEndian ? "most" : "least"));
+ } else {
+ rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth,
+ ((pf->bitsPerPixel == 8) ? ""
+ : (pf->bigEndian ? ", big endian" : ", little endian")));
+ if (pf->trueColour) {
+ rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n",
+ pf->redMax, pf->greenMax, pf->blueMax,
+ pf->redShift, pf->greenShift, pf->blueShift);
+ } else {
+ rfbLog(" uses a colour map (not true colour).\n");
+ }
+ }
+}
--- xorg-server-1.7.4/hw/vnc/vncauth.c
+++ xorg-server-1.7.4/hw/vnc/vncauth.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+ * vncauth.c - Functions for VNC password management and authentication.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <vncauth.h>
+#include <d3des.h>
+
+
+/*
+ * Make sure we call srandom() only once.
+ */
+
+static int s_srandom_called = 0;
+
+/*
+ * We use a fixed key to store passwords, since we assume that our local
+ * file system is secure but nonetheless don't want to store passwords
+ * as plaintext.
+ */
+
+static unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7};
+
+
+/*
+ * Encrypt a password and store it in a file. Returns 0 if successful,
+ * 1 if the file could not be written.
+ *
+ * NOTE: This function is preserved only for compatibility with the original
+ * AT&T VNC software. Use vncEncryptAndStorePasswd2() instead.
+ */
+
+int
+vncEncryptAndStorePasswd(char *passwd, char *fname)
+{
+ return (vncEncryptAndStorePasswd2(passwd, NULL, fname) == 0);
+}
+
+/*
+ * Encrypt one or two passwords and store them in a file. Returns 1 if
+ * successful, 0 if the file could not be written (note that the original
+ * vncEncryptAndStorePasswd() function returns inverse values). The
+ * passwdViewOnly pointer may be NULL.
+ *
+ * NOTE: The file name of "-" denotes stdout.
+ */
+
+int
+vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname)
+{
+ FILE *fp;
+ int bytesToWrite, bytesWrote;
+ unsigned char encryptedPasswd[16] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0
+ };
+
+ if (strcmp(fname, "-") != 0) {
+ fp = fopen(fname, "w");
+ if (fp == NULL) {
+ return 0;
+ }
+ chmod(fname, S_IRUSR|S_IWUSR);
+ } else {
+ fp = stdout;
+ }
+
+ strncpy((char*)encryptedPasswd, passwd, 8);
+ if (passwdViewOnly != NULL)
+ strncpy((char*)encryptedPasswd + 8, passwdViewOnly, 8);
+
+ /* Do encryption in-place - this way we overwrite our copies of
+ plaintext passwords. */
+
+ deskey(s_fixedkey, EN0);
+ des(encryptedPasswd, encryptedPasswd);
+ if (passwdViewOnly != NULL)
+ des(encryptedPasswd + 8, encryptedPasswd + 8);
+
+ bytesToWrite = (passwdViewOnly == NULL) ? 8 : 16;
+ bytesWrote = fwrite(encryptedPasswd, 1, bytesToWrite, fp);
+
+ if (fp != stdout) {
+ fclose(fp);
+ }
+ return (bytesWrote == bytesToWrite);
+}
+
+
+/*
+ * Decrypt a password from a file. Returns a pointer to a newly allocated
+ * string containing the password or a null pointer if the password could
+ * not be retrieved for some reason.
+ *
+ * NOTE: This function is preserved only for compatibility with the original
+ * AT&T VNC software. Use vncDecryptPasswdFromFile2() instead.
+ */
+
+char *
+vncDecryptPasswdFromFile(char *fname)
+{
+ char *passwd;
+
+ passwd = malloc(9);
+
+ if (passwd != NULL) {
+ if (vncDecryptPasswdFromFile2(fname, passwd, NULL) == 0) {
+ free(passwd);
+ passwd = NULL;
+ }
+ }
+
+ return passwd;
+}
+
+/*
+ * Decrypt one or two passwords from a file. Returns the number of
+ * passwords read (1, 2, or 0 on error). On success, the passwords are
+ * written into buffers passwdFullControl[] and passwdViewOnly[] if
+ * they are not NULL. If the pointers to buffers are not NULL, then
+ * the buffers should be at least of 9 bytes length.
+ */
+
+int
+vncDecryptPasswdFromFile2(char *fname,
+ char *passwdFullControl, char *passwdViewOnly)
+{
+ FILE *fp;
+ int i, ch;
+ unsigned char passwd[16];
+
+ if (strcmp(fname, "-") != 0) {
+ if ((fp = fopen(fname,"r")) == NULL)
+ return 0; /* Could not open the file */
+ } else {
+ fp = stdin;
+ }
+
+ for (i = 0; i < 16; i++) {
+ ch = getc(fp);
+ if (ch == EOF)
+ break;
+ passwd[i] = ch;
+ }
+
+ if (fp != stdin)
+ fclose(fp);
+
+ if (i < 8)
+ return 0; /* Could not read eight bytes */
+
+ deskey(s_fixedkey, DE1);
+
+ /* Decoding first (full-control) password */
+ if (passwdFullControl != NULL) {
+ des(passwd, passwd);
+ memcpy(passwdFullControl, passwd, 8);
+ passwdFullControl[8] = '\0';
+ }
+
+ /* Decoding second (view-only) password if available */
+ if (i == 16 && passwdViewOnly != NULL) {
+ des(&passwd[8], &passwd[8]);
+ memcpy(passwdViewOnly, &passwd[8], 8);
+ passwdViewOnly[8] = '\0';
+ }
+
+ /* Destroying our copy of clear-text passwords */
+ memset(passwd, 0, 16);
+
+ return (i < 16) ? 1 : 2;
+}
+
+
+/*
+ * Generate CHALLENGESIZE random bytes for use in challenge-response
+ * authentication.
+ */
+
+void
+vncRandomBytes(unsigned char *bytes)
+{
+ int i;
+ unsigned int seed;
+
+ if (!s_srandom_called) {
+ seed = (unsigned int)time(0) ^ (unsigned int)getpid();
+ srandom(seed);
+ s_srandom_called = 1;
+ }
+
+ for (i = 0; i < CHALLENGESIZE; i++) {
+ bytes[i] = (unsigned char)(random() & 255);
+ }
+}
+
+
+/*
+ * Encrypt CHALLENGESIZE bytes in memory using a password.
+ */
+
+void
+vncEncryptBytes(unsigned char *bytes, char *passwd)
+{
+ unsigned char key[8];
+ int i;
+
+ /* key is simply password padded with nulls */
+
+ for (i = 0; i < 8; i++) {
+ if (i < strlen(passwd)) {
+ key[i] = passwd[i];
+ } else {
+ key[i] = 0;
+ }
+ }
+
+ deskey(key, EN0);
+
+ for (i = 0; i < CHALLENGESIZE; i += 8) {
+ des(bytes+i, bytes+i);
+ }
+}
--- xorg-server-1.7.4/hw/vnc/vncauth.h
+++ xorg-server-1.7.4/hw/vnc/vncauth.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*
+ * vncauth.h - describes the functions provided by the vncauth library.
+ */
+
+#define MAXPWLEN 8
+#define CHALLENGESIZE 16
+
+extern int vncEncryptAndStorePasswd(char *passwd, char *fname);
+extern char *vncDecryptPasswdFromFile(char *fname);
+extern void vncRandomBytes(unsigned char *bytes);
+extern void vncEncryptBytes(unsigned char *bytes, char *passwd);
+extern int vncEncryptAndStorePasswd2(char *passwd, char *passwdViewOnly, char *fname);
+extern int vncDecryptPasswdFromFile2(char *fname, char *passwdFullControl, char *passwdViewOnly);
+
--- xorg-server-1.7.4/hw/vnc/vncext.c
+++ xorg-server-1.7.4/hw/vnc/vncext.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include "rfb.h"
+#include "extnsionst.h"
+#define _VNC_SERVER
+#include <X11/extensions/vncstr.h>
+#ifdef XFree86LOADER
+#include "xf86Module.h"
+#endif
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+DevPrivateKey vncCreateScreenResourcesKey = &vncCreateScreenResourcesKey;
+DevPrivateKey rfbGCKey = &rfbGCKey;
+
+int VncSelectNotify(ClientPtr client, BOOL onoff);
+void VncExtensionInit(void);
+
+static int VncErrorBase; /* first vnc error number */
+static int VncEventBase; /* first vnc event number */
+
+#define USE_ORIG_RES_CODE 0
+
+#if USE_ORIG_RES_CODE
+unsigned long VncResourceGeneration = 0;
+
+static RESTYPE VncNotifyList;
+
+static XID faked;
+
+typedef struct _VncNotifyListRec {
+ struct _VncNotifyListRec *next;
+ ClientPtr client;
+} VncNotifyListRec, *VncNotifyListPtr;
+#endif
+
+
+/**
+ * Each X client that uses libVnc to talk to this extension will
+ * get recorded by one of these records.
+ */
+typedef struct _VncClientRec {
+ ClientPtr client;
+ struct _VncClientRec *next;
+ XID fakeID;
+ RESTYPE res;
+} VncClientRec, *VncClientRecPtr;
+
+static VncClientRecPtr ClientsList = NULL;
+
+
+/**
+ * Remove client record from list
+ */
+static void
+VncRemoveClientRecord(ClientPtr client)
+{
+ /* XXX need 'deleteresource' flag? */
+ VncClientRecPtr p = ClientsList, prev = NULL;
+ rfbLog("%s client %p\n", __func__, (void *) client);
+ while (p) {
+ if (p->client == client) {
+ /* remove this one */
+ if (prev)
+ prev->next = p->next;
+ else
+ ClientsList = p->next;
+ xfree(p);
+ return;
+ }
+ prev = p;
+ p = p->next;
+ }
+}
+
+
+/**
+ * This callback will be called by X's resource manager to delete the
+ * given resource. We create one resource for each client. When X
+ * deletes the resource, we know the client is going away.
+ */
+static int
+VncDestroyClientResourceCallback(pointer pn, XID id)
+{
+ VncClientRecPtr rec = (VncClientRecPtr) pn;
+ VncRemoveClientRecord(rec->client);
+ return Success;
+}
+
+
+/**
+ * Add a client record to the list of clients (unless already in list).
+ * We'll create a new, unique resource for this client. This is used
+ * to detect when an X client goes away.
+ */
+static void
+VncSaveClientRecord(ClientPtr client)
+{
+ VncClientRecPtr rec = ClientsList;
+
+ rfbLog("%s saving client %p\n", __func__, (void *) client);
+
+ /* look if already in list */
+ while (rec) {
+ if (rec->client == client) {
+ return; /* already in list */
+ }
+ rec = rec->next;
+ }
+
+ /* allocate new client record */
+ rec = (VncClientRecPtr) xalloc(sizeof(VncClientRec));
+ if (rec) {
+ rec->client = client;
+ rec->fakeID = FakeClientID(client->index);
+ rec->res = CreateNewResourceType(VncDestroyClientResourceCallback);
+ if (!AddResource(rec->fakeID, rec->res, rec)) {
+ xfree(rec);
+ }
+
+ /* insert at head of list */
+ rec->next = ClientsList;
+ ClientsList = rec;
+ }
+}
+
+
+
+static int
+ProcVncQueryVersion(ClientPtr client)
+{
+ xVncQueryVersionReply rep;
+
+ REQUEST_SIZE_MATCH(xVncQueryVersionReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.majorVersion = VNC_MAJOR_VERSION;
+ rep.minorVersion = VNC_MINOR_VERSION;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncQueryVersionReply),
+ (char *)&rep);
+ return (client->noClientException);
+} /* ProcVncQueryVersion */
+
+static int
+ProcVncConnection(ClientPtr client)
+{
+ REQUEST(xVncConnectionReq);
+ xVncConnectionReply rep;
+
+ rfbUserAllow( stuff->sock, stuff->accept );
+
+ REQUEST_SIZE_MATCH(xVncConnectionReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.sock = 0;
+ rep.accept = 0;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.sock, n);
+ swaps(&rep.accept, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncConnectionReply),
+ (char *)&rep);
+ return (client->noClientException);
+} /* ProcVncConnection */
+
+static int
+ProcVncSelectNotify(ClientPtr client)
+{
+ REQUEST(xVncSelectNotifyReq);
+ xVncSelectNotifyReply rep;
+
+ VncSelectNotify(client, stuff->onoff);
+
+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncSelectNotifyReply),
+ (char *)&rep);
+ return (client->noClientException);
+
+}
+
+static int
+ProcVncListConnections(ClientPtr client)
+{
+ xVncListConnectionsReply rep;
+ rfbClientPtr cl;
+ int count = 0;
+ struct in_addr ipaddress;
+ xVncConnectionListInfo Info;
+
+ /* count connections */
+ for (cl = rfbClientHead; cl; cl = cl->next)
+#ifdef CHROMIUM
+ /*
+ * Fix this, as it should be generic, but we're only using it
+ * for Chromium at the moment, so we only list the connections
+ * that have a valid chromium encoding. We should be able to list
+ * any type requested. FIXME! XXXX
+ * See furthur down this function too!!!
+ */
+ if (cl->enableChromiumEncoding)
+#endif
+ count++;
+
+ REQUEST_SIZE_MATCH(xVncListConnectionsReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.count = count;
+ rep.length = count * sizeof(xVncConnectionListInfo) >> 2;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.count, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncListConnectionsReply),
+ (char *)&rep);
+
+ for (cl = rfbClientHead; cl; cl = cl->next) {
+#ifdef CHROMIUM
+ /*
+ * Fix this, as it should be generic, but we're only using it
+ * for Chromium at the moment, so we only list the connections
+ * that have a valid chromium encoding. We should be able to list
+ * any type requested. FIXME! XXXX
+ */
+ if (!cl->enableChromiumEncoding)
+ continue;
+#endif
+ inet_aton(cl->host, &ipaddress);
+ memcpy(&Info, &ipaddress, sizeof(struct in_addr));
+ WriteToClient(client, SIZEOF(xVncConnectionListInfo), (char*)&Info);
+ }
+
+ return (client->noClientException);
+} /* ProcVncListConnections */
+
+#ifdef CHROMIUM
+static int
+ProcVncChromiumStart(ClientPtr client)
+{
+ REQUEST(xVncChromiumStartReq);
+ xVncChromiumStartReply rep;
+
+ rfbSendChromiumStart(stuff->ipaddress, stuff->crServerPort, stuff->mothershipPort);
+
+ REQUEST_SIZE_MATCH(xVncChromiumStartReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncChromiumStartReply),
+ (char *)&rep);
+ return (client->noClientException);
+} /* ProcVncChromiumStart */
+
+static int
+ProcVncChromiumMonitor(ClientPtr client)
+{
+ REQUEST(xVncChromiumMonitorReq);
+ xVncChromiumMonitorReply rep;
+
+ rfbChromiumMonitorWindowID(stuff->cr_windowid, stuff->windowid);
+
+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xVncChromiumMonitorReply),
+ (char *)&rep);
+ return (client->noClientException);
+} /* ProcVncChromiumMonitor */
+#endif /* CHROMIUM */
+
+static int
+ProcVncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_VncQueryVersion:
+ return ProcVncQueryVersion(client);
+ case X_VncSelectNotify:
+ return ProcVncSelectNotify(client);
+ case X_VncConnection:
+ return ProcVncConnection(client);
+ case X_VncListConnections:
+ return ProcVncListConnections(client);
+#ifdef CHROMIUM
+ case X_VncChromiumStart:
+ return ProcVncChromiumStart(client);
+ case X_VncChromiumMonitor:
+ return ProcVncChromiumMonitor(client);
+#endif
+ default:
+ return BadRequest;
+ }
+} /* ProcVncDispatch */
+
+static int
+SProcVncQueryVersion(ClientPtr client)
+{
+ REQUEST(xVncQueryVersionReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncQueryVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion,n);
+ return ProcVncQueryVersion(client);
+} /* SProcVncQueryVersion */
+
+static int
+SProcVncSelectNotify(ClientPtr client)
+{
+ REQUEST(xVncSelectNotifyReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncSelectNotifyReq);
+ return ProcVncSelectNotify(client);
+} /* SProcVncSelectNotify */
+
+static int
+SProcVncListConnections(ClientPtr client)
+{
+ REQUEST(xVncListConnectionsReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncListConnectionsReq);
+ return ProcVncListConnections(client);
+} /* SProcVncListConnections */
+
+#ifdef CHROMIUM
+static int
+SProcVncChromiumStart(ClientPtr client)
+{
+ REQUEST(xVncChromiumStartReq);
+ register char n;
+
+ swaps(&stuff->ipaddress, n);
+ swaps(&stuff->crServerPort, n);
+ swaps(&stuff->mothershipPort, n);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncChromiumStartReq);
+ return ProcVncChromiumStart(client);
+} /* SProcVncChromiumStart */
+
+static int
+SProcVncChromiumMonitor(ClientPtr client)
+{
+ REQUEST(xVncChromiumMonitorReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->windowid, n);
+ swaps(&stuff->cr_windowid, n);
+ REQUEST_SIZE_MATCH(xVncChromiumMonitorReq);
+ return ProcVncChromiumMonitor(client);
+} /* SProcVncChromiumMonitor */
+#endif /* CHROMIUM */
+
+static int
+SProcVncConnection(ClientPtr client)
+{
+ REQUEST(xVncConnectionReq);
+ register char n;
+
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncConnectionReq);
+ swaps(&stuff->sock, n);
+ swaps(&stuff->accept,n);
+ return ProcVncConnection(client);
+} /* SProcVncConnection */
+
+static int
+SProcVncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_VncQueryVersion:
+ return SProcVncQueryVersion(client);
+ case X_VncSelectNotify:
+ return SProcVncSelectNotify(client);
+ case X_VncConnection:
+ return SProcVncConnection(client);
+ case X_VncListConnections:
+ return SProcVncListConnections(client);
+#ifdef CHROMIUM
+ case X_VncChromiumStart:
+ return SProcVncChromiumStart(client);
+ case X_VncChromiumMonitor:
+ return SProcVncChromiumMonitor(client);
+#endif
+ default:
+ return BadRequest;
+ }
+} /* SProcVncDispatch */
+
+static void
+SwapVncConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to)
+{
+ to->type = from->type;
+ to->detail = from->detail;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->connected, to->connected);
+}
+
+#ifdef CHROMIUM
+static void
+SwapVncChromiumConnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to)
+{
+ to->type = from->type;
+ to->detail = from->detail;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->connected, to->connected);
+}
+#endif
+
+static void
+SwapVncDisconnectedEvent(xVncConnectedEvent *from, xVncConnectedEvent *to)
+{
+ to->type = from->type;
+ to->detail = from->detail;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->connected, to->connected);
+}
+
+int
+GenerateVncConnectedEvent(int sock)
+{
+#if USE_ORIG_RES_CODE
+ VncNotifyListPtr pn;
+
+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList);
+#else
+ VncClientRecPtr pn = ClientsList;
+#endif
+
+ while (pn)
+ {
+ if (pn->client)
+ {
+ xVncConnectedEvent conn;
+ SOCKLEN_T peer_len;
+ struct sockaddr_in peer;
+
+ conn.type = VncEventBase + XVncConnected;
+ conn.sequenceNumber = pn->client->sequence;
+ conn.connected = sock;
+
+ peer_len = sizeof(peer);
+ if (getpeername(sock, (struct sockaddr *) &peer, &peer_len) == -1)
+ conn.ipaddress = 0;
+ else
+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr;
+
+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask,
+ NoEventMask, NullGrab);
+ }
+ pn = pn->next;
+ }
+
+ return 1;
+}
+
+
+
+#ifdef CHROMIUM
+int
+GenerateVncChromiumConnectedEvent(int sock)
+{
+#if USE_ORIG_RES_CODE
+ VncNotifyListPtr pn;
+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList);
+#else
+ VncClientRecPtr pn = ClientsList;
+#endif
+ rfbLog("Enter GenerateVncChromiumConnectedEvent\n");
+ while (pn)
+ {
+ if (pn->client)
+ {
+ xVncConnectedEvent conn;
+ SOCKLEN_T peer_len;
+ struct sockaddr_in peer;
+
+ rfbLog("Sending XVncChromiumConnected to client %p\n",
+ (void *) pn->client);
+
+ conn.type = VncEventBase + XVncChromiumConnected;
+ conn.sequenceNumber = pn->client->sequence;
+ conn.connected = sock;
+
+ peer_len = sizeof(peer);
+ if (getpeername(sock, (struct sockaddr *)&peer, &peer_len) == -1)
+ conn.ipaddress = 0;
+ else
+ conn.ipaddress = (CARD32)peer.sin_addr.s_addr;
+
+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask,
+ NoEventMask, NullGrab);
+ }
+ pn = pn->next;
+ }
+ return 1;
+}
+#endif /* CHROMIUM */
+
+
+int
+GenerateVncDisconnectedEvent(int sock)
+{
+#if USE_ORIG_RES_CODE
+ VncNotifyListPtr pn;
+
+ pn = (VncNotifyListPtr)LookupIDByType(faked, VncNotifyList);
+#else
+ VncClientRecPtr pn = ClientsList;
+#endif
+ rfbLog("GenerateVncDisconnectedEvent\n");
+ while (pn)
+ {
+ if (pn->client)
+ {
+ xVncDisconnectedEvent conn;
+ conn.type = VncEventBase + XVncDisconnected;
+ conn.sequenceNumber = pn->client->sequence;
+ conn.connected = sock;
+ (void) TryClientEvents(pn->client, (xEventPtr)&conn, 1, NoEventMask,
+ NoEventMask, NullGrab);
+ }
+ pn = pn->next;
+ }
+
+ return 1;
+}
+
+static void
+VncResetProc(ExtensionEntry *extEntry)
+{
+} /* VncResetProc */
+
+
+
+/**
+ * When the app calls libVnc's XVncSelectNotify() we wind up here.
+ * Either add or remove 'client' from the VncNotifyList depending on 'onoff'.
+ */
+int
+VncSelectNotify(ClientPtr client, BOOL onoff)
+{
+#if USE_ORIG_RES_CODE
+ VncNotifyListPtr head, newRec, tmp, freeRec = NULL;
+
+ rfbLog("%s client %p onoff=%d\n", __func__, (void *) client, (int) onoff);
+ if (!faked)
+ faked = FakeClientID(client->index);
+#else
+ /* ignore onoff param */
+ VncSaveClientRecord(client);
+#endif
+
+#if USE_ORIG_RES_CODE
+ /* Get the first VncNotifyListPtr */
+ head = (VncNotifyListPtr) LookupIDByType(faked, VncNotifyList);
+
+ /* search list for this client */
+ tmp = head;
+ while (tmp) {
+ if (tmp->client == client) {
+ /* found client! */
+ if (!onoff)
+ tmp->client = NULL;
+ return Success;
+ }
+ if (!tmp->client)
+ freeRec = tmp; /* save ptr to free record */
+ tmp = tmp->next;
+ }
+
+ /* if we get here, we didn't find client in the list */
+
+ if (!onoff) {
+ /* if turning off non-existing client, just return */
+ return Success;
+ }
+
+ /* OK, add new client to list now */
+
+ if (freeRec) {
+ /* re-using a free spot */
+ freeRec->client = client;
+ return Success;
+ }
+
+ /* need to allocate new node */
+ if (!(newRec = (VncNotifyListPtr)xalloc(sizeof(VncNotifyListRec))))
+ return BadAlloc;
+ /* insert at head, just as AddResource() does!!! */
+ newRec->next = head;
+ newRec->client = client;
+ if (!AddResource(faked, VncNotifyList, newRec)) {
+ xfree(newRec);
+ return BadAlloc;
+ }
+#endif
+ return Success;
+}
+
+
+#if USE_ORIG_RES_CODE
+static int
+VncDestroyNotifyList(pointer pn, XID id)
+{
+ VncNotifyListPtr cpn = (VncNotifyListPtr) pn;
+ rfbLog("%s client %p\n", __func__, (void *) cpn->client);
+ cpn->client = NULL;
+ return Success;
+}
+#endif
+
+static Bool
+CreateResourceTypes(void)
+{
+#if USE_ORIG_RES_CODE
+ if (VncResourceGeneration == serverGeneration)
+ return TRUE;
+
+ VncResourceGeneration = serverGeneration;
+
+ if (!(VncNotifyList = CreateNewResourceType(VncDestroyNotifyList))) {
+ ErrorF("CreateResourceTypes: failed to allocate vnc notify list resource.\n");
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+
+
+
+static unsigned long vncExtGeneration = 0;
+#if XFREE86VNC
+extern Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart);
+
+/* copied from miscrinit.c */
+typedef struct
+{
+ pointer pbits; /* pointer to framebuffer */
+ int width; /* delta to add to a framebuffer addr to move one row down */
+} miScreenInitParmsRec, *miScreenInitParmsPtr;
+
+
+static Bool
+vncCreateScreenResources(ScreenPtr pScreen)
+{
+ int ret = TRUE;
+ CreateScreenResourcesProcPtr CreateScreenResources =
+ (CreateScreenResourcesProcPtr)
+ dixLookupPrivate(&pScreen->devPrivates, vncCreateScreenResourcesKey);
+ miScreenInitParmsPtr pScrInitParms;
+
+ pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
+
+ if ( pScreen->CreateScreenResources != vncCreateScreenResources ) {
+ /* Can't find hook we are hung on */
+ xf86DrvMsg(pScreen->myNum, X_WARNING /* X_ERROR */,
+ "vncCreateScreenResources %p called when not in "
+ "pScreen->CreateScreenResources %p n",
+ (void *) vncCreateScreenResources,
+ (void *) pScreen->CreateScreenResources );
+ }
+
+ /* Now do our stuff */
+ VNCInit(pScreen, pScrInitParms->pbits);
+
+ /* Unhook this function ... */
+ pScreen->CreateScreenResources = CreateScreenResources;
+ dixSetPrivate(&pScreen->devPrivates, vncCreateScreenResourcesKey, NULL);
+
+ /* ... and call the previous CreateScreenResources fuction, if any */
+ if (pScreen->CreateScreenResources) {
+ ret = (*pScreen->CreateScreenResources)(pScreen);
+ }
+
+#ifdef DEBUG
+ ErrorF("vncCreateScreenResources() returns %d\n", ret);
+#endif
+ return ret;
+}
+#endif
+
+
+
+void
+VncExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ if (vncExtGeneration != serverGeneration) {
+ unsigned int i;
+
+ vncExtGeneration = serverGeneration;
+
+ // no allocation needed for screen privates
+ if (!dixRequestPrivate(rfbGCKey, sizeof(rfbGCRec)))
+ return;
+
+#if XFREE86VNC
+ for (i = 0 ; i < screenInfo.numScreens; i++)
+ {
+ dixSetPrivate(&screenInfo.screens[i]->devPrivates,
+ vncCreateScreenResourcesKey,
+ xf86Screens[i]->pScreen->CreateScreenResources);
+ xf86Screens[i]->pScreen->CreateScreenResources = vncCreateScreenResources;
+ }
+#endif
+
+ gethostname(rfbThisHost, 255);
+ }
+
+ if (!CreateResourceTypes())
+ return;
+
+ extEntry = AddExtension(VNC_EXTENSION_NAME,
+ XVncNumberEvents, XVncNumberErrors,
+ ProcVncDispatch, SProcVncDispatch,
+ VncResetProc, StandardMinorOpcode);
+
+ VncErrorBase = extEntry->errorBase;
+ VncEventBase = extEntry->eventBase;
+
+ EventSwapVector[VncEventBase + XVncConnected] =
+ (EventSwapPtr)SwapVncConnectedEvent;
+ EventSwapVector[VncEventBase + XVncDisconnected] =
+ (EventSwapPtr)SwapVncDisconnectedEvent;
+#ifdef CHROMIUM
+ EventSwapVector[VncEventBase + XVncChromiumConnected] =
+ (EventSwapPtr)SwapVncChromiumConnectedEvent;
+#endif
+} /* VncExtensionInit */
--- xorg-server-1.7.4/hw/vnc/xistubs.c
+++ xorg-server-1.7.4/hw/vnc/xistubs.c
@@ -0,0 +1,323 @@
+/* $Xorg: stubs.c,v 1.4 2001/02/09 02:04:35 xorgcvs Exp $ */
+
+/************************************************************
+
+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.
+
+Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ 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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-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.
+
+********************************************************/
+/* $XFree86: xc/programs/Xserver/Xi/stubs.c,v 3.3 2001/01/17 22:13:26 dawes Exp $ */
+
+/*
+ * stubs.c -- stub routines for the X server side of the XINPUT
+ * extension. This file is mainly to be used only as documentation.
+ * There is not much code here, and you can't get a working XINPUT
+ * server just using this.
+ * The Xvfb server uses this file so it will compile with the same
+ * object files as the real X server for a platform that has XINPUT.
+ * Xnest could do the same thing.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "inputstr.h"
+#include "XIstubs.h"
+
+/***********************************************************************
+ *
+ * Caller: ProcXChangeKeyboardDevice
+ *
+ * This procedure does the implementation-dependent portion of the work
+ * needed to change the keyboard device.
+ *
+ * The X keyboard device has a FocusRec. If the device that has been
+ * made into the new X keyboard did not have a FocusRec,
+ * ProcXChangeKeyboardDevice will allocate one for it.
+ *
+ * If you do not want clients to be able to focus the old X keyboard
+ * device, call DeleteFocusClassDeviceStruct to free the FocusRec.
+ *
+ * If you support input devices with keys that you do not want to be
+ * used as the X keyboard, you need to check for them here and return
+ * a BadDevice error.
+ *
+ * The default implementation is to do nothing (assume you do want
+ * clients to be able to focus the old X keyboard). The commented-out
+ * sample code shows what you might do if you don't want the default.
+ *
+ */
+
+int
+ChangeKeyboardDevice (old_dev, new_dev)
+ DeviceIntPtr old_dev;
+ DeviceIntPtr new_dev;
+ {
+ /***********************************************************************
+ DeleteFocusClassDeviceStruct(old_dev); * defined in xchgptr.c *
+ **********************************************************************/
+ return BadMatch;
+ }
+
+
+/***********************************************************************
+ *
+ * Caller: ProcXChangePointerDevice
+ *
+ * This procedure does the implementation-dependent portion of the work
+ * needed to change the pointer device.
+ *
+ * The X pointer device does not have a FocusRec. If the device that
+ * has been made into the new X pointer had a FocusRec,
+ * ProcXChangePointerDevice will free it.
+ *
+ * If you want clients to be able to focus the old pointer device that
+ * has now become accessible through the input extension, you need to
+ * add a FocusRec to it here.
+ *
+ * The XChangePointerDevice protocol request also allows the client
+ * to choose which axes of the new pointer device are used to move
+ * the X cursor in the X- and Y- directions. If the axes are different
+ * than the default ones, you need to keep track of that here.
+ *
+ * If you support input devices with valuators that you do not want to be
+ * used as the X pointer, you need to check for them here and return a
+ * BadDevice error.
+ *
+ * The default implementation is to do nothing (assume you don't want
+ * clients to be able to focus the old X pointer). The commented-out
+ * sample code shows what you might do if you don't want the default.
+ *
+ */
+
+int
+#if NeedFunctionPrototypes
+ChangePointerDevice (
+ DeviceIntPtr old_dev,
+ DeviceIntPtr new_dev,
+ unsigned char x,
+ unsigned char y)
+#else
+ChangePointerDevice (old_dev, new_dev, x, y)
+ DeviceIntPtr old_dev, new_dev;
+ unsigned char x, y;
+#endif
+ {
+ /***********************************************************************
+ InitFocusClassDeviceStruct(old_dev); * allow focusing old ptr*
+
+ x_axis = x; * keep track of new x-axis*
+ y_axis = y; * keep track of new y-axis*
+ if (x_axis != 0 || y_axis != 1)
+ axes_changed = TRUE; * remember axes have changed*
+ else
+ axes_changed = FALSE;
+ *************************************************************************/
+ return BadMatch;
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXCloseDevice
+ *
+ * Take care of implementation-dependent details of closing a device.
+ * Some implementations may actually close the device, others may just
+ * remove this clients interest in that device.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are initialized during X server initialization and kept open).
+ *
+ */
+
+void
+CloseInputDevice (d, client)
+ DeviceIntPtr d;
+ ClientPtr client;
+ {
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXListInputDevices
+ *
+ * This is the implementation-dependent routine to initialize an input
+ * device to the point that information about it can be listed.
+ * Some implementations open all input devices when the server is first
+ * initialized, and never close them. Other implementations open only
+ * the X pointer and keyboard devices during server initialization,
+ * and only open other input devices when some client makes an
+ * XOpenDevice request. If some other process has the device open, the
+ * server may not be able to get information about the device to list it.
+ *
+ * This procedure should be used by implementations that do not initialize
+ * all input devices at server startup. It should do device-dependent
+ * initialization for any devices not previously initialized, and call
+ * AddInputDevice for each of those devices so that a DeviceIntRec will be
+ * created for them.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are initialized during X server initialization and kept open).
+ * The commented-out sample code shows what you might do if you don't want
+ * the default.
+ *
+ */
+
+void
+AddOtherInputDevices ()
+ {
+ /**********************************************************************
+ for each uninitialized device, do something like:
+
+ DeviceIntPtr dev;
+ DeviceProc deviceProc;
+ pointer private;
+
+ dev = (DeviceIntPtr) AddInputDevice(deviceProc, TRUE);
+ dev->public.devicePrivate = private;
+ RegisterOtherDevice(dev);
+ dev->inited = ((*dev->deviceProc)(dev, DEVICE_INIT) == Success);
+ ************************************************************************/
+
+ }
+
+/***********************************************************************
+ *
+ * Caller: ProcXOpenDevice
+ *
+ * This is the implementation-dependent routine to open an input device.
+ * Some implementations open all input devices when the server is first
+ * initialized, and never close them. Other implementations open only
+ * the X pointer and keyboard devices during server initialization,
+ * and only open other input devices when some client makes an
+ * XOpenDevice request. This entry point is for the latter type of
+ * implementation.
+ *
+ * If the physical device is not already open, do it here. In this case,
+ * you need to keep track of the fact that one or more clients has the
+ * device open, and physically close it when the last client that has
+ * it open does an XCloseDevice.
+ *
+ * The default implementation is to do nothing (assume all input devices
+ * are opened during X server initialization and kept open).
+ *
+ */
+
+void
+OpenInputDevice (dev, client, status)
+ DeviceIntPtr dev;
+ ClientPtr client;
+ int *status;
+ {
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXSetDeviceMode
+ *
+ * Change the mode of an extension device.
+ * This function is used to change the mode of a device from reporting
+ * relative motion to reporting absolute positional information, and
+ * vice versa.
+ * The default implementation below is that no such devices are supported.
+ *
+ */
+
+int
+SetDeviceMode (client, dev, mode)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ int mode;
+ {
+ return BadMatch;
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXSetDeviceValuators
+ *
+ * Set the value of valuators on an extension input device.
+ * This function is used to set the initial value of valuators on
+ * those input devices that are capable of reporting either relative
+ * motion or an absolute position, and allow an initial position to be set.
+ * The default implementation below is that no such devices are supported.
+ *
+ */
+
+int
+SetDeviceValuators (client, dev, valuators, first_valuator, num_valuators)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ int *valuators;
+ int first_valuator;
+ int num_valuators;
+ {
+ return BadMatch;
+ }
+
+/****************************************************************************
+ *
+ * Caller: ProcXChangeDeviceControl
+ *
+ * Change the specified device controls on an extension input device.
+ *
+ */
+
+int
+ChangeDeviceControl (client, dev, control)
+ register ClientPtr client;
+ DeviceIntPtr dev;
+ xDeviceCtl *control;
+ {
+ switch (control->control)
+ {
+ case DEVICE_RESOLUTION:
+ return (BadMatch);
+ default:
+ return (BadMatch);
+ }
+ }
--- xorg-server-1.7.4/hw/vnc/zlib.c
+++ xorg-server-1.7.4/hw/vnc/zlib.c
@@ -0,0 +1,310 @@
+/*
+ * zlib.c
+ *
+ * Routines to implement zlib based encoding (deflate).
+ *
+ * Modified for XFree86 4.x by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * For the latest source code, please check:
+ *
+ * http://www.developVNC.org/
+ *
+ * or send email to feedback@developvnc.org.
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+
+#include <stdio.h>
+#include "rfb.h"
+
+/*
+ * zlibBeforeBuf contains pixel data in the client's format.
+ * zlibAfterBuf contains the zlib (deflated) encoding version.
+ * If the zlib compressed/encoded version is
+ * larger than the raw data or if it exceeds zlibAfterBufSize then
+ * raw encoding is used instead.
+ */
+
+static int zlibBeforeBufSize = 0;
+static unsigned char *zlibBeforeBuf = NULL;
+
+static int zlibAfterBufSize = 0;
+static unsigned char *zlibAfterBuf = NULL;
+static int zlibAfterBufLen;
+
+/*
+ * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib
+ * rectangle encoding.
+ */
+
+Bool
+rfbSendOneRectEncodingZlib(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ rfbFramebufferUpdateRectHeader rect;
+ rfbZlibHeader hdr;
+ int deflateResult;
+ int previousOut;
+ int i;
+ int maxRawSize;
+ int maxCompSize;
+
+ maxRawSize = (pVNC->width * pVNC->height
+ * (cl->format.bitsPerPixel / 8));
+
+ if (zlibBeforeBufSize < maxRawSize) {
+ zlibBeforeBufSize = maxRawSize;
+ if (zlibBeforeBuf == NULL)
+ zlibBeforeBuf = (unsigned char *)xalloc(zlibBeforeBufSize);
+ else
+ zlibBeforeBuf = (unsigned char *)xrealloc(zlibBeforeBuf, zlibBeforeBufSize);
+ }
+
+ /* zlib compression is not useful for very small data sets.
+ * So, we just send these raw without any compression.
+ */
+ if (( w * h * (pVNC->bitsPerPixel / 8)) <
+ VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) {
+
+ int result;
+
+ /* The translation function (used also by the in raw encoding)
+ * requires 4/2/1 byte alignment in the output buffer (which is
+ * pVNC->updateBuf for the raw encoding) based on the bitsPerPixel of
+ * the viewer/client. This prevents SIGBUS errors on some
+ * architectures like SPARC, PARISC...
+ */
+ if (( cl->format.bitsPerPixel > 8 ) &&
+ ( pVNC->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ result = rfbSendRectEncodingRaw(cl, x, y, w, h);
+
+ return result;
+
+ }
+
+ /*
+ * zlib requires output buffer to be slightly larger than the input
+ * buffer, in the worst case.
+ */
+ maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12;
+
+ if (zlibAfterBufSize < maxCompSize) {
+ zlibAfterBufSize = maxCompSize;
+ if (zlibAfterBuf == NULL)
+ zlibAfterBuf = (unsigned char *)xalloc(zlibAfterBufSize);
+ else
+ zlibAfterBuf = (unsigned char *)xrealloc(zlibAfterBuf, zlibAfterBufSize);
+ }
+
+ /*
+ * Convert pixel data to client format.
+ */
+ (*cl->translateFn)(cl->pScreen, cl->translateLookupTable,
+ &pVNC->rfbServerFormat,
+ &cl->format, zlibBeforeBuf,
+ pVNC->paddedWidthInBytes, w, h, x, y);
+
+ cl->compStream.next_in = ( Bytef * )zlibBeforeBuf;
+ cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8);
+ cl->compStream.next_out = ( Bytef * )zlibAfterBuf;
+ cl->compStream.avail_out = maxCompSize;
+ cl->compStream.data_type = Z_BINARY;
+
+ /* Initialize the deflation state. */
+ if ( cl->compStreamInited == FALSE ) {
+
+ cl->compStream.total_in = 0;
+ cl->compStream.total_out = 0;
+ cl->compStream.zalloc = Z_NULL;
+ cl->compStream.zfree = Z_NULL;
+ cl->compStream.opaque = Z_NULL;
+
+ deflateInit2( &(cl->compStream),
+ cl->zlibCompressLevel,
+ Z_DEFLATED,
+ MAX_WBITS,
+ MAX_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY );
+ /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */
+ /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */
+ cl->compStreamInited = TRUE;
+
+ }
+
+ previousOut = cl->compStream.total_out;
+
+ /* Perform the compression here. */
+ deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH );
+
+ /* Find the total size of the resulting compressed data. */
+ zlibAfterBufLen = cl->compStream.total_out - previousOut;
+
+ if ( deflateResult != Z_OK ) {
+ rfbLog("zlib deflation error: %s\n", cl->compStream.msg);
+ return FALSE;
+ }
+
+ /* Note that it is not possible to switch zlib parameters based on
+ * the results of the compression pass. The reason is
+ * that we rely on the compressor and decompressor states being
+ * in sync. Compressing and then discarding the results would
+ * cause lose of synchronization.
+ */
+
+ /* Update statics */
+ cl->rfbRectanglesSent[rfbEncodingZlib]++;
+ cl->rfbBytesSent[rfbEncodingZlib] += (sz_rfbFramebufferUpdateRectHeader
+ + sz_rfbZlibHeader + zlibAfterBufLen);
+
+ if (pVNC->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader
+ > UPDATE_BUF_SIZE)
+ {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.r.x = Swap16IfLE(x);
+ rect.r.y = Swap16IfLE(y);
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+ rect.encoding = Swap32IfLE(rfbEncodingZlib);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ pVNC->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ hdr.nBytes = Swap32IfLE(zlibAfterBufLen);
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], (char *)&hdr, sz_rfbZlibHeader);
+ pVNC->ublen += sz_rfbZlibHeader;
+
+ for (i = 0; i < zlibAfterBufLen;) {
+
+ int bytesToCopy = UPDATE_BUF_SIZE - pVNC->ublen;
+
+ if (i + bytesToCopy > zlibAfterBufLen) {
+ bytesToCopy = zlibAfterBufLen - i;
+ }
+
+ memcpy(&pVNC->updateBuf[pVNC->ublen], &zlibAfterBuf[i], bytesToCopy);
+
+ pVNC->ublen += bytesToCopy;
+ i += bytesToCopy;
+
+ if (pVNC->ublen == UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+
+}
+
+
+/*
+ * rfbSendRectEncodingZlib - send a given rectangle using one or more
+ * Zlib encoding rectangles.
+ */
+
+Bool
+rfbSendRectEncodingZlib(cl, x, y, w, h)
+ rfbClientPtr cl;
+ int x, y, w, h;
+{
+ VNCSCREENPTR(cl->pScreen);
+ int maxLines;
+ int linesRemaining;
+ rfbRectangle partialRect;
+
+ partialRect.x = x;
+ partialRect.y = y;
+ partialRect.w = w;
+ partialRect.h = h;
+
+ /* Determine maximum pixel/scan lines allowed per rectangle. */
+ maxLines = ( ZLIB_MAX_SIZE(w) / w );
+
+ /* Initialize number of scan lines left to do. */
+ linesRemaining = h;
+
+ /* Loop until all work is done. */
+ while ( linesRemaining > 0 ) {
+
+ int linesToComp;
+
+ if ( maxLines < linesRemaining )
+ linesToComp = maxLines;
+ else
+ linesToComp = linesRemaining;
+
+ partialRect.h = linesToComp;
+
+ /* Encode (compress) and send the next rectangle. */
+ if ( ! rfbSendOneRectEncodingZlib( cl,
+ partialRect.x,
+ partialRect.y,
+ partialRect.w,
+ partialRect.h )) {
+
+ return FALSE;
+ }
+
+ /* Technically, flushing the buffer here is not extrememly
+ * efficient. However, this improves the overall throughput
+ * of the system over very slow networks. By flushing
+ * the buffer with every maximum size zlib rectangle, we
+ * improve the pipelining usage of the server CPU, network,
+ * and viewer CPU components. Insuring that these components
+ * are working in parallel actually improves the performance
+ * seen by the user.
+ * Since, zlib is most useful for slow networks, this flush
+ * is appropriate for the desired behavior of the zlib encoding.
+ */
+ if (( pVNC->ublen > 0 ) &&
+ ( linesToComp == maxLines )) {
+ if (!rfbSendUpdateBuf(cl)) {
+
+ return FALSE;
+ }
+ }
+
+ /* Update remaining and incremental rectangle location. */
+ linesRemaining -= linesToComp;
+ partialRect.y += linesToComp;
+
+ }
+
+ return TRUE;
+
+}
+
+
--- xorg-server-1.7.4/hw/xfree86/Makefile.am
+++ xorg-server-1.7.4/hw/xfree86/Makefile.am
@@ -4,6 +4,10 @@
DRI_SUBDIR = dri
endif
+if VNC
+VNC_SUBDIR = vnc
+endif
+
if DRI2
DRI2_SUBDIR = dri2
endif
@@ -32,13 +36,13 @@
SUBDIRS = common ddc i2c x86emu $(INT10_SUBDIR) fbdevhw os-support parser \
ramdac shadowfb $(VBE_SUBDIR) $(VGAHW_SUBDIR) $(XAA_SUBDIR) \
- xf8_16bpp loader dixmods exa modes \
+ xf8_16bpp loader dixmods exa modes $(VNC_SUBDIR) \
$(DRI_SUBDIR) $(DRI2_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR)
DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
parser ramdac shadowfb vbe vgahw xaa \
xf8_16bpp loader dixmods dri dri2 exa modes \
- utils doc
+ utils doc vnc
bin_PROGRAMS = Xorg
Xorg_SOURCES = xorg.c
--- xorg-server-1.7.4/hw/xfree86/dixmods/Makefile.am
+++ xorg-server-1.7.4/hw/xfree86/dixmods/Makefile.am
@@ -10,6 +10,10 @@
DBEMOD = libdbe.la
endif
+if XCLIPLIST
+XCLIPLISTMOD = libxcliplist.la
+endif
+
if RECORD
RECORDMOD = librecord.la
endif
@@ -21,11 +25,13 @@
extsmoduledir = $(moduledir)/extensions
extsmodule_LTLIBRARIES = $(RECORDMOD) \
$(DBEMOD) \
+ $(XCLIPLISTMOD) \
$(GLXMODS)
AM_CFLAGS = @XORG_CFLAGS@ @DIX_CFLAGS@
INCLUDES = @XORG_INCS@ \
-I$(top_srcdir)/dbe \
+ -I$(top_srcdir)/xcliplist \
-I$(top_srcdir)/hw/xfree86/loader \
-I$(top_srcdir)/miext/shadow \
-I$(top_srcdir)/glx
@@ -34,6 +40,10 @@
libdbe_la_LIBADD = $(top_builddir)/dbe/libdbe.la
libdbe_la_SOURCES = dbemodule.c
+libxcliplist_la_LDFLAGS = -avoid-version
+libxcliplist_la_LIBADD = $(top_builddir)/xcliplist/libxcliplist.la
+libxcliplist_la_SOURCES = $(top_srcdir)/xcliplist/cliplistmod.c
+
libfb_la_LDFLAGS = -avoid-version
libfb_la_LIBADD = $(top_builddir)/fb/libfb.la
libfb_la_SOURCES = $(top_builddir)/fb/fbcmap_mi.c fbmodule.c
--- xorg-server-1.7.4/hw/xfree86/vnc/.gitignore
+++ xorg-server-1.7.4/hw/xfree86/vnc/.gitignore
@@ -0,0 +1,36 @@
+auth.c
+cmap.c
+corre.c
+cursor.c
+cutpaste.c
+d3des.c
+d3des.h
+dispcur.c
+draw.c
+hextile.c
+httpd.c
+kbdptr.c
+keyboard.h
+loginauth.c
+rdp.c
+rfb.h
+rfbkeyb.c
+rfbmouse.c
+rfbproto.h
+rfbserver.c
+rre.c
+sockets.c
+sprite.c
+sprite.h
+spritest.h
+stats.c
+tableinitcmtemplate.c
+tableinittctemplate.c
+tabletranstemplate.c
+tight.c
+translate.c
+vncauth.c
+vncauth.h
+vncext.c
+xistubs.c
+zlib.c
--- xorg-server-1.7.4/hw/xfree86/vnc/Makefile.am
+++ xorg-server-1.7.4/hw/xfree86/vnc/Makefile.am
@@ -0,0 +1,51 @@
+AM_CFLAGS = $(DIX_CFLAGS)
+
+libvnc_la_LTLIBRARIES = libvnc.la
+libvnc_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \
+ -I$(top_srcdir)/hw/xfree86/os-support \
+ -I$(top_srcdir)/hw/xfree86/os-support/bus \
+ -I$(top_srcdir)/mi \
+ -I$(top_srcdir)/render \
+ -I$(top_srcdir)/GL/glx \
+ -I$(top_srcdir)/GL/include \
+ -I$(top_builddir)/GL/include \
+ -I@MESA_SOURCE@/include \
+ -DHAVE_XORG_CONFIG_H \
+ -DHAVE_DIX_CONFIG_H \
+ -DXFree86LOADER \
+ -DXFREE86VNC=1 \
+ -DCHROMIUM=1 \
+ $(AM_CFLAGS)
+
+libvnc_la_LIBADD = -ljpeg -lcrypt
+libvnc_la_LDFLAGS = -module -avoid-version
+libvnc_ladir = $(moduledir)/extensions
+libvnc_la_SOURCES = \
+ auth.c \
+ cmap.c \
+ corre.c \
+ cursor.c \
+ cutpaste.c \
+ d3des.c \
+ dispcur.c \
+ draw.c \
+ hextile.c \
+ httpd.c \
+ kbdptr.c \
+ loginauth.c \
+ rdp.c \
+ rfbkeyb.c \
+ rfbmouse.c \
+ rfbserver.c \
+ rre.c \
+ sockets.c \
+ sprite.c \
+ stats.c \
+ tight.c \
+ translate.c \
+ vncInit.c \
+ vncauth.c \
+ vncext.c \
+ zlib.c
+
+#sdk_HEADERS = vncint.h
--- xorg-server-1.7.4/hw/xfree86/vnc/README
+++ xorg-server-1.7.4/hw/xfree86/vnc/README
@@ -0,0 +1 @@
+This directory contains the sources for building the vnc.so server extension module.
--- xorg-server-1.7.4/hw/xfree86/vnc/vncInit.c
+++ xorg-server-1.7.4/hw/xfree86/vnc/vncInit.c
@@ -0,0 +1,618 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <netinet/in.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../ramdac/xf86CursorPriv.h"
+#include "rfb.h"
+#include "vncint.h"
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "xf86Resources.h"
+#include "xf86Version.h"
+
+int vncScreenPrivateIndex = -1;
+int inetdSock = -1;
+Atom VNC_LAST_CLIENT_ID = 0;
+Atom VNC_CONNECT = 0;
+char *desktopName = "x11";
+char rfbThisHost[256];
+
+DevPrivateKey VNCScreenKey = &VNCScreenKey;
+
+extern void VncExtensionInit(void);
+
+Bool VNCInit(ScreenPtr pScreen, unsigned char *FBStart);
+
+#ifndef XFree86LOADER
+static unsigned long VNCGeneration = 0;
+#endif
+static const OptionInfoRec *VNCAvailableOptions(void *unused);
+static void rfbWakeupHandler (int i, pointer blockData, unsigned long err, pointer pReadmask);
+
+static Bool vncCursorRealizeCursor(ScreenPtr, CursorPtr);
+static Bool vncCursorUnrealizeCursor(ScreenPtr, CursorPtr);
+static void vncCursorSetCursor(ScreenPtr, CursorPtr, int, int);
+static void vncCursorMoveCursor(ScreenPtr, int, int);
+static Bool vncDisplayCursor(ScreenPtr, CursorPtr);
+
+static miPointerSpriteFuncRec vncCursorSpriteFuncs = {
+ vncCursorRealizeCursor,
+ vncCursorUnrealizeCursor,
+ vncCursorSetCursor,
+ vncCursorMoveCursor
+};
+
+/*
+ * VNC Config options
+ */
+
+typedef enum {
+ OPTION_USEVNC,
+ OPTION_RFBPORT,
+ OPTION_HTTPPORT,
+ OPTION_ALWAYS_SHARED,
+ OPTION_NEVER_SHARED,
+ OPTION_DONT_DISCONNECT,
+ OPTION_HTTPDIR,
+ OPTION_PASSWD_FILE,
+ OPTION_USER_ACCEPT,
+ OPTION_LOCALHOST,
+ OPTION_INTERFACE,
+ OPTION_VIEWONLY,
+ OPTION_LOGIN_AUTH,
+} VNCOpts;
+
+static const OptionInfoRec VNCOptions[] = {
+ {OPTION_USEVNC, "usevnc", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_RFBPORT, "rfbport", OPTV_INTEGER, {0}, FALSE },
+ {OPTION_HTTPPORT, "httpport", OPTV_INTEGER, {0}, FALSE },
+ {OPTION_ALWAYS_SHARED, "alwaysshared", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_NEVER_SHARED, "nevershared", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_DONT_DISCONNECT, "dontdisconnect", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_HTTPDIR, "httpdir", OPTV_STRING, {0}, FALSE },
+ {OPTION_PASSWD_FILE, "rfbauth", OPTV_STRING, {0}, FALSE },
+ {OPTION_USER_ACCEPT, "useraccept", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_LOCALHOST, "localhost", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_INTERFACE, "interface", OPTV_STRING, {0}, FALSE },
+ {OPTION_VIEWONLY, "viewonly", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_LOGIN_AUTH, "loginauth", OPTV_BOOLEAN, {0}, FALSE },
+ { -1, NULL, OPTV_NONE, {0}, FALSE }
+};
+
+/*ARGSUSED*/
+static const OptionInfoRec *
+VNCAvailableOptions(void *unused)
+{
+ return (VNCOptions);
+}
+
+/*
+ * rfbLog prints a time-stamped message to the log file (stderr).
+ */
+
+void rfbLog(char *format, ...)
+{
+ va_list ap;
+ char buf[256];
+ time_t clock;
+
+ time(&clock);
+ strftime(buf, 255, "%d/%m/%Y %H:%M:%S ", localtime(&clock));
+ xf86DrvMsgVerb(-1, X_INFO, 1, buf);
+
+ va_start(ap, format);
+ xf86VDrvMsgVerb(-1, X_NONE, 1, format, ap);
+ va_end(ap);
+}
+
+void rfbLogPerror(char *str)
+{
+ rfbLog("");
+ perror(str);
+}
+
+/*
+ * Called by vncCreateScreenResources()
+ */
+Bool
+VNCInit(ScreenPtr pScreen, unsigned char *FBStart)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ VisualPtr visual;
+ vncScreenPtr pScreenPriv;
+ OptionInfoPtr options;
+ char *interface_str = NULL;
+ miPointerScreenPtr PointPriv;
+ xf86CursorScreenPtr xf86CursorPriv;
+#ifdef RENDER
+ PictureScreenPtr ps;
+#endif
+
+ if (!FBStart)
+ return FALSE;
+
+#ifndef XFree86LOADER
+ if (VNCGeneration != serverGeneration) {
+ VncExtensionInit();
+ VNCGeneration = serverGeneration;
+ }
+#endif
+
+ if (!(pScreenPriv = xalloc(sizeof(vncScreenRec))))
+ return FALSE;
+
+ dixSetPrivate(&pScreen->devPrivates, VNCScreenKey, pScreenPriv);
+
+ options = xnfalloc(sizeof(VNCOptions));
+ (void)memcpy(options, VNCOptions, sizeof(VNCOptions));
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
+
+ if (xf86ReturnOptValBool(options, OPTION_USEVNC, FALSE)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VNC enabled\n");
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC disabled\n");
+ xfree(options);
+ return FALSE;
+ }
+
+ pScreenPriv->rfbAuthTries = 0;
+ pScreenPriv->rfbAuthTooManyTries = FALSE;
+ pScreenPriv->timer = NULL;
+ pScreenPriv->udpPort = 0;
+ pScreenPriv->rfbListenSock = -1;
+ pScreenPriv->udpSock = -1;
+ pScreenPriv->udpSockConnected = FALSE;
+ pScreenPriv->httpListenSock = -1;
+ pScreenPriv->httpSock = -1;
+ pScreenPriv->maxFd = 0;
+ pScreenPriv->rfbAuthPasswdFile = NULL;
+ pScreenPriv->httpDir = NULL;
+ pScreenPriv->rfbInstalledColormap = NULL;
+ pScreenPriv->interface.s_addr = htonl (INADDR_ANY);
+
+ pScreenPriv->rfbPort = 0;
+ xf86GetOptValInteger(options, OPTION_RFBPORT, &pScreenPriv->rfbPort);
+ pScreenPriv->httpPort = 0;
+ xf86GetOptValInteger(options, OPTION_HTTPPORT, &pScreenPriv->httpPort);
+ pScreenPriv->rfbAuthPasswdFile =
+ xf86GetOptValString(options, OPTION_PASSWD_FILE);
+ pScreenPriv->httpDir =
+ xf86GetOptValString(options, OPTION_HTTPDIR);
+ pScreenPriv->rfbAlwaysShared = FALSE;
+ xf86GetOptValBool(options, OPTION_ALWAYS_SHARED,
+ &pScreenPriv->rfbAlwaysShared);
+ pScreenPriv->rfbNeverShared = FALSE;
+ xf86GetOptValBool(options, OPTION_NEVER_SHARED,
+ &pScreenPriv->rfbNeverShared);
+ pScreenPriv->rfbUserAccept = FALSE;
+ xf86GetOptValBool(options, OPTION_USER_ACCEPT,
+ &pScreenPriv->rfbUserAccept);
+ pScreenPriv->rfbViewOnly = FALSE;
+ xf86GetOptValBool(options, OPTION_VIEWONLY,
+ &pScreenPriv->rfbViewOnly);
+ pScreenPriv->rfbDontDisconnect = FALSE;
+ xf86GetOptValBool(options, OPTION_DONT_DISCONNECT,
+ &pScreenPriv->rfbDontDisconnect);
+ pScreenPriv->loginAuthEnabled = FALSE;
+ xf86GetOptValBool(options, OPTION_LOGIN_AUTH,
+ &pScreenPriv->loginAuthEnabled);
+
+ if (xf86ReturnOptValBool(options, OPTION_LOCALHOST, FALSE))
+ pScreenPriv->interface.s_addr = htonl (INADDR_LOOPBACK);
+
+ interface_str = xf86GetOptValString(options, OPTION_INTERFACE);
+
+ if (interface_str && pScreenPriv->interface.s_addr == htonl(INADDR_ANY)) {
+ Bool failed = FALSE;
+ struct in_addr got;
+ unsigned long octet;
+ char *p = interface_str, *end;
+ int q;
+
+ for (q = 0; q < 4; q++) {
+ octet = strtoul (p, &end, 10);
+
+ if (p == end || octet > 255)
+ failed = TRUE;
+
+ if ((q < 3 && *end != '.') ||
+ (q == 3 && *end != '\0'))
+ failed = TRUE;
+
+ got.s_addr = (got.s_addr << 8) | octet;
+ p = end + 1;
+ }
+
+ if (!failed)
+ pScreenPriv->interface.s_addr = htonl (got.s_addr);
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VNC interface option malformed, not using.\n");
+ }
+
+ xfree(options);
+
+ if (!VNC_LAST_CLIENT_ID)
+ VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID",
+ strlen("VNC_LAST_CLIENT_ID"), TRUE);
+ if (!VNC_CONNECT)
+ VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE);
+
+ rfbInitSockets(pScreen);
+ if (inetdSock == -1)
+ httpInitSockets(pScreen);
+
+#ifdef CORBA
+ initialiseCORBA(argc, argv, desktopName);
+#endif
+
+ pScreenPriv->width = pScrn->virtualX;
+ pScreenPriv->height = pScrn->virtualY;
+ pScreenPriv->depth = pScrn->depth;
+ pScreenPriv->paddedWidthInBytes = PixmapBytePad(pScrn->displayWidth, pScrn->depth);
+ pScreenPriv->bitsPerPixel = rfbBitsPerPixel(pScrn->depth);
+ pScreenPriv->pfbMemory = FBStart;
+ pScreenPriv->oldpfbMemory = FBStart;
+
+ pScreenPriv->cursorIsDrawn = TRUE;
+ pScreenPriv->dontSendFramebufferUpdate = FALSE;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->CreateGC = pScreen->CreateGC;
+ pScreenPriv->PaintWindowBackground = pScreen->PaintWindowBackground;
+ pScreenPriv->PaintWindowBorder = pScreen->PaintWindowBorder;
+ pScreenPriv->CopyWindow = pScreen->CopyWindow;
+ pScreenPriv->ClearToBackground = pScreen->ClearToBackground;
+ pScreenPriv->RestoreAreas = pScreen->RestoreAreas;
+ pScreenPriv->WakeupHandler = pScreen->WakeupHandler;
+ pScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess;
+ pScreenPriv->InstallColormap = pScreen->InstallColormap;
+ pScreenPriv->UninstallColormap = pScreen->UninstallColormap;
+ pScreenPriv->ListInstalledColormaps = pScreen->ListInstalledColormaps;
+ pScreenPriv->StoreColors = pScreen->StoreColors;
+ pScreenPriv->DisplayCursor = pScreen->DisplayCursor;
+#ifdef CHROMIUM
+ pScreenPriv->RealizeWindow = pScreen->RealizeWindow;
+ pScreenPriv->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreenPriv->DestroyWindow = pScreen->DestroyWindow;
+ pScreenPriv->PositionWindow = pScreen->PositionWindow;
+ pScreenPriv->ResizeWindow = pScreen->ResizeWindow;
+ pScreenPriv->ClipNotify = pScreen->ClipNotify;
+#endif
+#ifdef RENDER
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps)
+ pScreenPriv->Composite = ps->Composite;
+#endif
+ pScreen->CloseScreen = rfbCloseScreen;
+ pScreen->CreateGC = rfbCreateGC;
+ pScreen->PaintWindowBackground = rfbPaintWindowBackground;
+ pScreen->PaintWindowBorder = rfbPaintWindowBorder;
+ pScreen->CopyWindow = rfbCopyWindow;
+ pScreen->ClearToBackground = rfbClearToBackground;
+ pScreen->RestoreAreas = rfbRestoreAreas;
+ pScreen->WakeupHandler = rfbWakeupHandler;
+ pScrn->EnableDisableFBAccess = rfbEnableDisableFBAccess;
+ pScreen->InstallColormap = rfbInstallColormap;
+ pScreen->UninstallColormap = rfbUninstallColormap;
+ pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
+ pScreen->StoreColors = rfbStoreColors;
+ pScreen->DisplayCursor = vncDisplayCursor; /* it's defined in here */
+
+#ifdef CHROMIUM
+ pScreen->RealizeWindow = rfbRealizeWindow;
+ pScreen->UnrealizeWindow = rfbUnrealizeWindow;
+ pScreen->DestroyWindow = rfbDestroyWindow;
+ pScreen->PositionWindow = rfbPositionWindow;
+ pScreen->ResizeWindow = rfbResizeWindow;
+ pScreen->ClipNotify = rfbClipNotify;
+#endif
+#ifdef RENDER
+ if (ps)
+ ps->Composite = rfbComposite;
+#endif
+
+ for (visual = pScreen->visuals; visual->vid != pScreen->rootVisual; visual++)
+ ;
+
+ if (!visual) {
+ ErrorF("rfbScreenInit: couldn't find root visual\n");
+ return FALSE;
+ }
+
+ pScreenPriv->rfbServerFormat.bitsPerPixel = pScrn->bitsPerPixel;
+ pScreenPriv->rfbServerFormat.depth = pScrn->depth;
+ pScreenPriv->rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
+ pScreenPriv->rfbServerFormat.trueColour = (visual->class == TrueColor);
+ if (pScreenPriv->rfbServerFormat.trueColour) {
+ pScreenPriv->rfbServerFormat.redMax = visual->redMask >> visual->offsetRed;
+ pScreenPriv->rfbServerFormat.greenMax = visual->greenMask >> visual->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueMax = visual->blueMask >> visual->offsetBlue;
+ pScreenPriv->rfbServerFormat.redShift = visual->offsetRed;
+ pScreenPriv->rfbServerFormat.greenShift = visual->offsetGreen;
+ pScreenPriv->rfbServerFormat.blueShift = visual->offsetBlue;
+ } else {
+ pScreenPriv->rfbServerFormat.redMax
+ = pScreenPriv->rfbServerFormat.greenMax
+ = pScreenPriv->rfbServerFormat.blueMax = 0;
+ pScreenPriv->rfbServerFormat.redShift
+ = pScreenPriv->rfbServerFormat.greenShift
+ = pScreenPriv->rfbServerFormat.blueShift = 0;
+ }
+
+ PointPriv = dixLookupPrivate(&(pScreen)->devPrivates, miPointerScreenKey);
+
+ pScreenPriv->spriteFuncs = PointPriv->spriteFuncs;
+ PointPriv->spriteFuncs = &vncCursorSpriteFuncs;
+
+ xf86CursorPriv = dixLookupPrivate(&(pScreen)->devPrivates, xf86CursorScreenKey);
+
+ if (xf86CursorPriv) {
+ pScreenPriv->UseHWCursor = xf86CursorPriv->CursorInfoPtr->UseHWCursor;
+ xf86CursorPriv->CursorInfoPtr->UseHWCursor = vncUseHWCursor;
+#ifdef ARGB_CURSOR
+ pScreenPriv->UseHWCursorARGB = xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB;
+ xf86CursorPriv->CursorInfoPtr->UseHWCursorARGB = vncUseHWCursorARGB;
+#endif
+ pScreenPriv->SWCursor = &xf86CursorPriv->SWCursor;
+ }
+
+ return TRUE;
+}
+
+/****** miPointerSpriteFunctions *******/
+
+static Bool
+vncCursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+
+ return (*pScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs);
+}
+
+static Bool
+vncCursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs)
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+
+ return (*pScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs);
+}
+
+static void
+vncCursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+
+ pScreenPriv->pCurs = pCurs;
+
+ /* Without this call, cursor changes only appear in the viewer when
+ * some other drawing has occured. Added by BrianP.
+ */
+ rfbScheduleUpdate(pScreen);
+
+#if 0
+ if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */
+ if (pScreenPriv->cursorIsDrawn)
+ pScreenPriv->cursorIsDrawn = FALSE;
+ return;
+ }
+
+ pScreenPriv->cursorIsDrawn = TRUE;
+#endif
+
+ (*pScreenPriv->spriteFuncs->SetCursor)(pScreen, pCurs, x, y);
+}
+
+static void
+vncCursorMoveCursor(ScreenPtr pScreen, int x, int y)
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ rfbClientPtr cl;
+
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (cl->enableCursorPosUpdates)
+ cl->cursorWasMoved = TRUE;
+ }
+
+ (*pScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y);
+}
+
+Bool
+vncUseHWCursor(pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ rfbClientPtr cl;
+
+ if (!*pScreenPriv->UseHWCursor) {
+ /* If the driver doesn't have a UseHWCursor function we're
+ * basically saying we can have the HWCursor on all the time
+ */
+ pScreenPriv->SWCursor = (Bool *)FALSE;
+ return TRUE;
+ }
+
+ pScreenPriv->SWCursor = (Bool *)FALSE;
+
+ /* If someone's connected, we revert to software cursor */
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (!cl->enableCursorShapeUpdates)
+ pScreenPriv->SWCursor = (Bool *)TRUE;
+ }
+
+ if (pScreenPriv->SWCursor == (Bool *)TRUE)
+ return FALSE;
+
+ return (*pScreenPriv->UseHWCursor)(pScreen, pCursor);
+}
+
+#ifdef ARGB_CURSOR
+#include "cursorstr.h"
+
+Bool
+vncUseHWCursorARGB(pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ rfbClientPtr cl;
+
+ if (!*pScreenPriv->UseHWCursorARGB) {
+ pScreenPriv->SWCursor = (Bool *)TRUE;
+ return FALSE;
+ }
+
+ pScreenPriv->SWCursor = (Bool *)FALSE;
+
+ /* If someone's connected, we revert to software cursor */
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (!cl->enableCursorShapeUpdates)
+ pScreenPriv->SWCursor = (Bool *)TRUE;
+ }
+
+ if (pScreenPriv->SWCursor == (Bool *)TRUE)
+ return FALSE;
+
+ return (*pScreenPriv->UseHWCursorARGB)(pScreen, pCursor);
+}
+#endif
+
+static Bool
+vncDisplayCursor(pScreen, pCursor)
+ ScreenPtr pScreen;
+ CursorPtr pCursor;
+{
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ rfbClientPtr cl;
+ Bool ret;
+
+ pScreen->DisplayCursor = pScreenPriv->DisplayCursor;
+
+ for (cl = rfbClientHead; cl ; cl = cl->next) {
+ if (cl->enableCursorShapeUpdates)
+ cl->cursorWasChanged = TRUE;
+ }
+
+ ret = (*pScreen->DisplayCursor)(pScreen, pCursor);
+
+ pScreen->DisplayCursor = vncDisplayCursor;
+
+ return ret;
+}
+
+static void
+rfbWakeupHandler (
+ int i,
+ pointer blockData,
+ unsigned long err,
+ pointer pReadmask
+){
+ ScreenPtr pScreen = screenInfo.screens[i];
+ vncScreenPtr pScreenPriv = VNCPTR(pScreen);
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ int sigstate = xf86BlockSIGIO();
+
+ rfbRootPropertyChange(pScreen); /* Check clipboard */
+
+ if (pScrn->vtSema) {
+ rfbCheckFds(pScreen);
+ httpCheckFds(pScreen);
+#ifdef CORBA
+ corbaCheckFds();
+#endif
+ } else {
+ rfbCheckFds(pScreen);
+ }
+
+ xf86UnblockSIGIO(sigstate);
+
+ pScreen->WakeupHandler = pScreenPriv->WakeupHandler;
+ (*pScreen->WakeupHandler) (i, blockData, err, pReadmask);
+ pScreen->WakeupHandler = rfbWakeupHandler;
+}
+
+#ifdef XFree86LOADER
+static MODULESETUPPROTO(vncSetup);
+
+static XF86ModuleVersionInfo vncVersRec =
+{
+ "vnc",
+ "xf4vnc Project, see http://xf4vnc.sf.net (based on modular X.org)",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ 1, 1, 0,
+ ABI_CLASS_EXTENSION,
+#if 0
+ ABI_EXTENSION_VERSION,
+#else
+ /* Hack to allow module to work with more servers (vs. 0.3 above) */
+ SET_ABI_VERSION(0, 2),
+#endif
+ MOD_CLASS_EXTENSION,
+ {0,0,0,0}
+};
+
+XF86ModuleData vncModuleData = {
+ &vncVersRec, /* vers */
+ vncSetup, /* ModuleSetupProc */
+ NULL /* ModuleTearDownProc */
+};
+
+ModuleInfoRec VNC = {
+ 1, /* moduleVersion */
+ "VNC", /* moduleName */
+ NULL, /* module pointer */
+ 0, /* refCount */
+ VNCAvailableOptions, /* function returning array of OptionsInfoRec */
+};
+
+ExtensionModule vncExtensionModule = {
+ VncExtensionInit, /* initFunc */
+ "VNC", /* name */
+ NULL, /* disablePtr */
+ NULL, /* setupFunc */
+ NULL /* initDependencies */
+};
+
+
+/*ARGSUSED*/
+static pointer
+vncSetup(pointer Module, pointer Options, int *ErrorMajor, int *ErrorMinor)
+{
+ LoadExtension(&vncExtensionModule, FALSE);
+ /* add mouse/kbd input drivers */
+ vncInitMouse();
+ vncInitKeyb();
+ xf86Msg(X_INFO, "Ignore errors regarding the loading of the rfbmouse & rfbkeyb drivers\n");
+
+ return (pointer)TRUE;
+}
+#endif
--- xorg-server-1.7.4/hw/xfree86/vnc/vncint.h
+++ xorg-server-1.7.4/hw/xfree86/vnc/vncint.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2002 Alan Hourihane. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ *
+ * Author: Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+#ifndef _VNC_H_
+#define _VNC_H_
+
+#include <../ramdac/xf86Cursor.h>
+
+#define VNCPTR(pScreen)\
+ (vncScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, VNCScreenKey))
+
+typedef struct {
+ int rfbPort;
+ int rdpPort;
+ int udpPort;
+ int rfbListenSock;
+ int rdpListenSock;
+ int udpSock;
+ int httpPort;
+ int httpListenSock;
+ int httpSock;
+ char * httpDir;
+ char buf[HTTP_BUF_SIZE];
+ Bool udpSockConnected;
+ char * rfbAuthPasswdFile;
+ size_t buf_filled;
+ int maxFd;
+ fd_set allFds;
+ unsigned char * oldpfbMemory;
+ Bool rfbAlwaysShared;
+ Bool rfbNeverShared;
+ Bool rfbDontDisconnect;
+ Bool rfbUserAccept;
+ Bool rfbViewOnly;
+ unsigned char * pfbMemory;
+ int paddedWidthInBytes;
+ ColormapPtr rfbInstalledColormap;
+ ColormapPtr savedColormap;
+ rfbPixelFormat rfbServerFormat;
+ Bool rfbAuthTooManyTries;
+ int rfbAuthTries;
+ Bool loginAuthEnabled;
+ struct in_addr interface;
+ OsTimerPtr timer;
+ unsigned char updateBuf[UPDATE_BUF_SIZE];
+ int ublen;
+ int width;
+ int height;
+ int depth;
+ int bitsPerPixel;
+
+ /* The following two members are used to minimise the amount of unnecessary
+ drawing caused by cursor movement. Whenever any drawing affects the
+ part of the screen where the cursor is, the cursor is removed first and
+ then the drawing is done (this is what the sprite routines test for).
+ Afterwards, however, we do not replace the cursor, even when the cursor
+ is logically being moved across the screen. We only draw the cursor
+ again just as we are about to send the client a framebuffer update.
+
+ We need to be careful when removing and drawing the cursor because of
+ their relationship with the normal drawing routines. The drawing
+ routines can invoke the cursor routines, but also the cursor routines
+ themselves end up invoking drawing routines.
+
+ Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by
+ doing a CopyArea from a pixmap to the screen, where the pixmap contains
+ the saved contents of the screen under the cursor. Before doing this,
+ however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
+ it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
+ (recursively!) remove the cursor before doing it.
+
+ Putting up the cursor (rfbSpriteRestoreCursor) involves a call to
+ PushPixels. While this is happening, cursorIsDrawn must be FALSE so
+ that PushPixels doesn't think it has to remove the cursor first.
+ Obviously cursorIsDrawn is set to TRUE afterwards.
+
+ Another problem we face is that drawing routines sometimes cause a
+ framebuffer update to be sent to the RFB client. When the RFB client is
+ already waiting for a framebuffer update and some drawing to the
+ framebuffer then happens, the drawing routine sees that the client is
+ ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
+ at this stage, it must be put up, and so rfbSpriteRestoreCursor is
+ called. However, if the original drawing routine was actually called
+ from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
+ want this to happen. So both the cursor routines set
+ dontSendFramebufferUpdate to TRUE, and all the drawing routines check
+ this before calling rfbSendFramebufferUpdate. */
+
+ Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
+ Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
+ cursor */
+
+ /* wrapped screen functions */
+
+ CloseScreenProcPtr CloseScreen;
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ RestoreAreasProcPtr RestoreAreas;
+ ScreenWakeupHandlerProcPtr WakeupHandler;
+ InstallColormapProcPtr InstallColormap;
+ UninstallColormapProcPtr UninstallColormap;
+ ListInstalledColormapsProcPtr ListInstalledColormaps;
+ StoreColorsProcPtr StoreColors;
+ xf86EnableDisableFBAccessProc *EnableDisableFBAccess;
+ miPointerSpriteFuncPtr spriteFuncs;
+ DisplayCursorProcPtr DisplayCursor;
+ CursorPtr pCurs;
+ Bool (*UseHWCursor)(ScreenPtr, CursorPtr);
+ Bool (*UseHWCursorARGB)(ScreenPtr, CursorPtr);
+ Bool *SWCursor;
+#ifdef CHROMIUM
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ PositionWindowProcPtr PositionWindow;
+ ClipNotifyProcPtr ClipNotify;
+#endif
+#ifdef RENDER
+ CompositeProcPtr Composite;
+#endif
+
+} vncScreenRec, *vncScreenPtr;
+
+extern Bool vncUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
+extern Bool vncUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs);
+extern void rfbEnableDisableFBAccess (int index, Bool enable);
+
+#endif /* _VNC_H_ */
+
--- xorg-server-1.7.4/mi/miinitext.c
+++ xorg-server-1.7.4/mi/miinitext.c
@@ -90,6 +90,18 @@
#undef XF86VIDMODE
#endif
+#ifdef VNCSERVER
+#undef COMPOSITE
+#undef DAMAGE
+#undef DBE
+#undef RANDR
+#undef XF86MISC
+#undef XFreeXDGA
+#undef XF86DRI
+#undef XF86VIDMODE
+#undef XFIXES
+#endif
+
#include "misc.h"
#include "extension.h"
#include "micmap.h"
--- xorg-server-1.7.4/xcliplist/Makefile.am
+++ xorg-server-1.7.4/xcliplist/Makefile.am
@@ -0,0 +1,18 @@
+#noinst_LTLIBRARIES = libxcliplist.la
+libxcliplist_la_LTLIBRARIES = libxcliplist.la
+
+#AM_CFLAGS = $(DIX_CFLAGS) @SERVER_DEFINES@ @LOADER_DEFINES@
+AM_CFLAGS = $(DIX_CFLAGS)
+
+libxcliplist_la_LDFLAGS = -module -avoid-version
+libxcliplist_ladir = $(moduledir)/extensions
+
+libxcliplist_la_SOURCES = \
+ cliplist.c \
+ cliplistmod.c
+
+## cliplistmod.c
+
+if XORG
+sdk_HEADERS =
+endif
--- xorg-server-1.7.4/xcliplist/cliplist.c
+++ xorg-server-1.7.4/xcliplist/cliplist.c
@@ -0,0 +1,128 @@
+/*
+ * Server-side code for the Xcliplist extension
+ */
+
+#if HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "windowstr.h"
+
+#define _XCLIPLIST_SERVER_
+#include <X11/extensions/Xclipliststr.h>
+
+
+static int XClipListErrorBase;
+static unsigned char XClipListReqCode = 0;
+
+static void
+XClipListResetProc(ExtensionEntry* extEntry)
+{
+ (void)extEntry;
+}
+
+static int
+ProcXClipListQueryVersion(ClientPtr client)
+{
+ xXClipListQueryVersionReply rep;
+
+ REQUEST_SIZE_MATCH(xXClipListQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XCLIPLIST_MAJOR_VERSION;
+ rep.minorVersion = XCLIPLIST_MINOR_VERSION;
+ rep.patchVersion = XCLIPLIST_PATCH_VERSION;
+
+ WriteToClient(client, sizeof(xXClipListQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcXGetClipList(ClientPtr client)
+{
+ xXGetClipListReply rep;
+ WindowPtr pWin;
+ int i;
+ BoxPtr pClipRects = NULL;
+ short xorig, yorig;
+ REQUEST(xXGetClipListReq);
+ REQUEST_SIZE_MATCH(xXGetClipListReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ if(!(pWin = (WindowPtr)LOOKUP_DRAWABLE(stuff->windowid, client) ))
+ {
+ client->errorValue = stuff->windowid;
+ return (BadWindow);
+ }
+
+ rep.num_entries = REGION_NUM_RECTS(&pWin->clipList);
+
+ WriteToClient(client, sizeof(xXGetClipListReply), (char *)&rep);
+
+ pClipRects = REGION_RECTS(&pWin->clipList);
+
+ xorig = pWin->drawable.x;
+ yorig = pWin->drawable.y;
+
+ for (i = 0; i < rep.num_entries; i++) {
+ BoxRec box;
+ /* translate clip rect from screen coords to window coords */
+ box.x1 = pClipRects[i].x1 - xorig;
+ box.y1 = pClipRects[i].y1 - yorig;
+ box.x2 = pClipRects[i].x2 - xorig;
+ box.y2 = pClipRects[i].y2 - yorig;
+ /*memcpy(&box, &pClipRects[i], sizeof(BoxRec));*/
+ WriteToClient(client, sizeof(BoxRec), (char *)&box);
+ }
+
+ return (client->noClientException);
+}
+
+static int
+ProcXClipListDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_XClipListQueryVersion:
+ return ProcXClipListQueryVersion(client);
+ case X_XGetClipList:
+ return ProcXGetClipList(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcXClipListDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+ (void)stuff;
+ return XClipListErrorBase + XClipListClientNotLocal;
+}
+
+void
+XClipListExtensionInit(void)
+{
+ ExtensionEntry* extEntry;
+
+ if ((extEntry = AddExtension(XCLIPLISTNAME,
+ XClipListNumberEvents,
+ XClipListNumberErrors,
+ ProcXClipListDispatch,
+ SProcXClipListDispatch,
+ XClipListResetProc,
+ StandardMinorOpcode))) {
+ XClipListReqCode = (unsigned char)extEntry->base;
+ XClipListErrorBase = extEntry->errorBase;
+ }
+}
--- xorg-server-1.7.4/xcliplist/cliplistmod.c
+++ xorg-server-1.7.4/xcliplist/cliplistmod.c
@@ -0,0 +1,46 @@
+
+#include "../hw/xfree86/common/xf86Module.h"
+
+extern Bool noTestExtensions;
+
+static MODULESETUPPROTO(xcliplistSetup);
+
+extern void XClipListExtensionInit(INITARGS);
+
+ExtensionModule xcliplistExt = {
+ XClipListExtensionInit,
+ "XClipList",
+ &noTestExtensions,
+ NULL,
+ NULL
+};
+
+static XF86ModuleVersionInfo VersRec = {
+ "XClipList",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT, /* XXX fix? */
+ 1, 13, 0,
+ ABI_CLASS_EXTENSION,
+#if 0
+ ABI_EXTENSION_VERSION,
+#else
+ /* Hack to allow module to work with more servers (vs. 0.3 above) */
+ SET_ABI_VERSION(0, 2),
+#endif
+ MOD_CLASS_EXTENSION,
+ {0,0,0,0}
+};
+
+XF86ModuleData xcliplistModuleData = { &VersRec, xcliplistSetup, NULL };
+
+static pointer
+xcliplistSetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ LoadExtension(&xcliplistExt, FALSE);
+
+ /* Need a non-NULL return value to indicate success */
+ return (pointer)1;
+}
+