+++ /dev/null
-diff -bcr xc.org/programs/Xserver/Imakefile xc/programs/Xserver/Imakefile
-*** xc.org/programs/Xserver/Imakefile 2004-12-15 20:22:53.000000000 +0100
---- xc/programs/Xserver/Imakefile 2005-02-14 14:23:21.000000000 +0100
-***************
-*** 128,134 ****
- LIBREGEX = RegexLibrary
-
- #if DoLoadableServer
-! LIBCWRAPPER = os/libcwrapper.o
- #endif
-
- #if BuildXprint
---- 128,134 ----
- LIBREGEX = RegexLibrary
-
- #if DoLoadableServer
-! LIBCWRAPPER = os/libcwrapper.o os/libos.a
- #endif
-
- #if BuildXprint
-***************
-*** 414,419 ****
---- 414,430 ----
- #define ServerToInstall Xsun
- #endif
- #endif /* XsunServer */
-+ XCOMM
-+ XCOMM X VNC server
-+ XCOMM
-+ FBSUBDIR = fb
-+ XVNCDDXDIR = vnc/Xvnc
-+ XVNCDIRS = $(STDDIRS) $(FBSUBDIR) miext/damage $(XVNCDDXDIR) $(DEPDIRS)
-+ XVNCLIBS = PreFbLibs vnc/Xvnc/LibraryTargetName(xvnc) FbPostFbLibs
-+ XVNCOBJS = $(XVNCDDXDIR)/stubs.o $(XVNCDDXDIR)/miinitext.o
-+ XVNCSYSLIBS = $(FONTLIBS) $(SYSLIBS)
-+ ServerTarget(Xvnc,$(XVNCDIRS),$(XVNCOBJS), \
-+ $(LIBCWRAPPER) $(XVNCLIBS) $(LOADABLEEXTS),$(XVNCSYSLIBS))
-
-
- #if defined(Xsun24Server) && Xsun24Server
-diff -bcr xc.org/programs/Xserver/mi/miinitext.c xc/programs/Xserver/mi/miinitext.c
-*** xc.org/programs/Xserver/mi/miinitext.c 2004-12-13 06:48:41.000000000 +0100
---- xc/programs/Xserver/mi/miinitext.c 2005-02-11 16:47:34.000000000 +0100
-***************
-*** 286,291 ****
---- 286,294 ----
- #ifdef MITMISC
- extern void MITMiscExtensionInit(INITARGS);
- #endif
-+ #ifdef VNCEXT
-+ extern void vncExtensionInit(INITARGS);
-+ #endif
- #ifdef XIDLE
- extern void XIdleExtensionInit(INITARGS);
- #endif
-***************
-*** 587,592 ****
---- 590,598 ----
- #ifdef MITMISC
- if (!noMITMiscExtension) MITMiscExtensionInit();
- #endif
-+ #ifdef VNCEXT
-+ vncExtensionInit();
-+ #endif
- #ifdef XIDLE
- if (!noXIdleExtension) XIdleExtensionInit();
- #endif
+++ /dev/null
-#include <vnc.def>
+++ /dev/null
-#define BuildServersOnly YES
-#define BuildFonts NO
-#define BuildClients NO
-#define BuildDocs NO
-#define BuildPexExt NO
-#define BuildNls NO
-#define BuildXIE NO
-#define BuildGlxExt YES
-#define GlxBuiltInXMesa YES
-#define XnestServer YES
-#define XF86Server NO
-#define XprtServer NO
-#define BuildXFree86ConfigTools NO
-
-#ifdef SunArchitecture
-#define ProjectRoot /usr/openwin
-#define HasGcc3 YES
-#endif
-
-#define HasFreetype2 NO
-#define BuildVNCExt YES
-#define VNCExtDefines -DVNCEXT
-#define SiteExtensionDefines VNCExtDefines
-#define SiteExtensionDirs vnc
-
-#define VncUnixDir $(TOP)/..
-#define VncCommonDir VncUnixDir/../common
-#define VncExtLibs VncCommonDir/rfb/librfb.a \
- VncCommonDir/Xregion/libXregion.a \
- VncCommonDir/network/libnetwork.a \
- VncCommonDir/rdr/librdr.a \
- VncCommonDir/jpeg/build/libjpeg.a
-
-#define SiteExtensionLibs vnc/LibraryTargetName(vnc) VncExtLibs
-
-#define ServerTarget(server,subdirs,objects,libs,syslibs) @@\
-CCLINK = $(CXXENVSETUP) $(CXX) @@\
-ServerTargetWithFlags(server,subdirs,objects,libs,syslibs,$(_NOOP_))
+++ /dev/null
-.TH Xvnc 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing"
-.SH NAME
-Xvnc \- the X VNC server
-.SH SYNOPSIS
-.B Xvnc
-.RI [ options ]
-.RI : display#
-.SH DESCRIPTION
-.B Xvnc
-is the X VNC (Virtual Network Computing) server. It is based on a standard X
-server, but it has a "virtual" screen rather than a physical one. X
-applications display themselves on it as if it were a normal X display, but
-they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1).
-
-So Xvnc is really two servers in one. To the applications it is an X server,
-and to the remote VNC users it is a VNC server. By convention we have arranged
-that the VNC server display number will be the same as the X server display
-number, which means you can use eg. snoopy:2 to refer to display 2 on machine
-"snoopy" in both the X world and the VNC world.
-
-The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This
-sets up the environment appropriately and runs some X applications to get you
-going. See the manual page for \fBvncserver\fP(1) for more information.
-
-.SH OPTIONS
-.B Xvnc
-takes lots of options - running \fBXvnc -help\fP gives a list. Many of these
-are standard X server options, which are described in the \fBXserver\fP(1)
-manual page. In addition to options which can only be set via the
-command-line, there are also "parameters" which can be set both via the
-command-line and through the \fBvncconfig\fP(1) program.
-
-.TP
-.B \-geometry \fIwidth\fPx\fIheight\fP
-Specify the size of the desktop to be created. Default is 1024x768.
-
-.TP
-.B \-depth \fIdepth\fP
-Specify the pixel depth in bits of the desktop to be created. Default is 16,
-other possible values are 8, 15, and 24 - anything else is likely to cause
-strange behaviour by applications.
-
-.TP
-.B \-pixelformat \fIformat\fP
-Specify pixel format for server to use (BGRnnn or RGBnnn). The default for
-depth 8 is BGR233 (meaning the most significant two bits represent blue, the
-next three green, and the least significant three represent red), the default
-for depth 16 is RGB565 and for depth 24 is RGB888.
-
-.TP
-.B \-cc 3
-As an alternative to the default TrueColor visual, this allows you to run an
-Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
-palette), which can be useful for running some old X applications which only
-work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor)
-for the \-cc option may result in strange behaviour, and PseudoColor desktops
-must be 8 bits deep (i.e. \fB-depth 8\fP).
-
-.TP
-.B \-inetd
-This significantly changes Xvnc's behaviour so that it can be launched from
-inetd. See the section below on usage with inetd.
-
-.TP
-.B \-help
-List all the options and parameters
-
-.SH PARAMETERS
-VNC parameters can be set both via the command-line and through the
-\fBvncconfig\fP(1) program, and with a VNC-enabled XFree86 server via Options
-entries in the XF86Config file.
-
-Parameters can be turned on with -\fIparam\fP or off with
--\fIparam\fP=0. Parameters which take a value can be specified as
--\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP
--\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are
-case-insensitive.
-
-.TP
-.B \-desktop \fIdesktop-name\fP
-Each desktop has a name which may be displayed by the viewer. It defaults to
-"x11".
-
-.TP
-.B \-rfbport \fIport\fP
-Specifies the TCP port on which Xvnc listens for connections from viewers (the
-protocol used in VNC is called RFB - "remote framebuffer"). The default is
-5900 plus the display number.
-
-.TP
-.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
-
-Time in milliseconds to wait for a viewer which is blocking Xvnc. This is
-necessary because Xvnc is single-threaded and sometimes blocks until the viewer
-has finished sending or receiving a message - note that this does not mean an
-update will be aborted after this time. Default is 20000 (20 seconds).
-
-.TP
-.B \-httpd \fIdirectory\fP
-Run a mini-HTTP server which serves files from the given directory. Normally
-the directory will contain the classes for the Java viewer. In addition, files
-with a .vnc extension will have certain substitutions made so that a single
-installation of the Java VNC viewer can be served by separate instances of
-Xvnc.
-
-.TP
-.B \-httpPort \fIport\fP
-Specifies the port on which the mini-HTTP server runs. Default is 5800 plus
-the display number.
-
-.TP
-.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
-Specifies the file containing the password used to authenticate viewers. The
-file is accessed each time a connection comes in, so it can be changed on the
-fly via \fBvncpasswd\fP(1).
-
-.TP
-.B \-deferUpdate \fItime\fP
-Xvnc uses a "deferred update" mechanism which enhances performance in many
-cases. After any change to the framebuffer, Xvnc waits for this number of
-milliseconds (default 40) before sending an update to any waiting clients. This
-means that more changes tend to get coalesced together in a single
-update. Setting it to 0 results in the same behaviour as earlier versions of
-Xvnc, where the first change to the framebuffer causes an immediate update to
-any waiting clients.
-
-.TP
-.B \-SendCutText
-Send clipboard changes to clients (default is on). Note that you must also run
-\fBvncconfig\fP(1) to get the clipboard to work.
-
-.TP
-.B \-AcceptCutText
-Accept clipboard updates from clients (default is on). Note that you must also
-run \fBvncconfig\fP(1) to get the clipboard to work.
-
-.TP
-.B \-AcceptPointerEvents
-Accept pointer press and release events from clients (default is on).
-
-.TP
-.B \-AcceptKeyEvents
-Accept key press and release events from clients (default is on).
-
-.TP
-.B \-DisconnectClients
-Disconnect existing clients if an incoming connection is non-shared (default is
-on). If \fBDisconnectClients\fP is false, then a new non-shared connection will
-be refused while there is a client active. When combined with
-\fBNeverShared\fP this means only one client is allowed at a time.
-
-.TP
-.B \-NeverShared
-Never treat incoming connections as shared, regardless of the client-specified
-setting (default is off).
-
-.TP
-.B \-AlwaysShared
-Always treat incoming connections as shared, regardless of the client-specified
-setting (default is off).
-
-.TP
-.B \-Protocol3.3
-Always use protocol version 3.3 for backwards compatibility with badly-behaved
-clients (default is off).
-
-.TP
-.B \-CompareFB
-Perform pixel comparison on framebuffer to reduce unnecessary updates (default
-is on).
-
-.TP
-.B \-SecurityTypes \fIsec-types\fP
-Specify which security schemes to use separated by commas. At present only
-"None" and "VncAuth" are supported. The default is "VncAuth" - note that if
-you want a server which does not require a password, you must set this
-parameter to "None".
-
-.TP
-.B \-IdleTimeout \fIseconds\fP
-The number of seconds after which an idle VNC connection will be dropped
-(default is 0, which means that idle connections will never be dropped).
-
-.TP
-.B \-QueryConnect
-Prompts the user of the desktop to explicitly accept or reject incoming
-connections. This is most useful when using the vnc.so module or
-\fBx0vncserver\fP(1) program to access an existing X desktop via VNC.
-
-The \fBvncconfig\fP(1) program must be running on the desktop in order for
-QueryConnect to be supported by the \fBvnc.so\fP(1) module or
-\fBXvnc\fP(1) program. The \fBx0vncserver\fP(1) program does not require
-\fBvncconfig\fP(1) to be running.
-
-.TP
-.B \-localhost
-Only allow connections from the same machine. Useful if you use SSH and want to
-stop non-SSH connections from any other hosts. See the guide to using VNC with
-SSH on the web site.
-
-.TP
-.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
-Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or
-\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose
-output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a
-specific source file if you know the name of its "LogWriter". Default is
-\fB*:stderr:30\fP.
-
-.TP
-.B \-RemapKeys \fImapping
-Sets up a keyboard mapping.
-.I mapping
-is a comma-separated string of character mappings, each of the form
-.IR char -> char ,
-or
-.IR char <> char ,
-where
-.I char
-is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following:
-.IP "" 10
-RemapKeys=0x22<>0x40
-
-.SH USAGE WITH INETD
-By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
-on demand when a connection comes in, rather than having to be started
-manually. When given the \fB-inetd\fP option, instead of listening for TCP
-connections on a given port it uses its standard input and standard output.
-There are two modes controlled by the wait/nowait entry in the inetd.conf file.
-
-In the nowait mode, Xvnc uses its standard input and output directly as the
-connection to a viewer. It never has a listening socket, so cannot accept
-further connections from viewers (it can however connect out to listening
-viewers by use of the vncconfig program). Further viewer connections to the
-same TCP port result in inetd spawning off a new Xvnc to deal with each
-connection. When the connection to the viewer dies, the Xvnc and any
-associated X clients die. This behaviour is most useful when combined with the
-XDMCP options -query and -once. An typical example in inetd.conf might be (all
-on one line):
-
-5950 stream tcp nowait nobody /usr/local/bin/Xvnc Xvnc -inetd -query
-localhost -once securitytypes=none
-
-In this example a viewer connection to :50 will result in a new Xvnc for that
-connection which should display the standard XDM login screen on that machine.
-Because the user needs to login via XDM, it is usually OK to accept connections
-without a VNC password in this case.
-
-In the wait mode, when the first connection comes in, inetd gives the listening
-socket to Xvnc. This means that for a given TCP port, there is only ever one
-Xvnc at a time. Further viewer connections to the same port are accepted by
-the same Xvnc in the normal way. Even when the original connection is broken,
-the Xvnc will continue to run. If this is used with the XDMCP options -query
-and -once, the Xvnc and associated X clients will die when the user logs out of
-the X session in the normal way. It is important to use a VNC password in this
-case. A typical entry in inetd.conf might be:
-
-5951 stream tcp wait james /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd
-
-In fact typically, you would have one entry for each user who uses VNC
-regularly, each of whom has their own dedicated TCP port which they use. In
-this example, when user "james" connects to :51, he enters his VNC password,
-then gets the XDM login screen where he logs in in the normal way. However,
-unlike the previous example, if he disconnects, the session remains persistent,
-and when he reconnects he will get the same session back again. When he logs
-out of the X session, the Xvnc will die, but of course a new one will be
-created automatically the next time he connects.
-
-.SH SEE ALSO
-.BR vncconfig (1),
-.BR vncpasswd (1),
-.BR vncserver (1),
-.BR vncviewer (1),
-.BR Xserver (1),
-.BR inetd (1)
-.br
-http://www.tightvnc.com
-
-.SH AUTHOR
-Tristan Richardson, RealVNC Ltd.
-
-VNC was originally developed by the RealVNC team while at Olivetti
-Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
-implemented by Constantin Kaplinsky. Many other people participated in
-development, testing and support.
+++ /dev/null
-XCOMM CDEBUGFLAGS = -g
-XCOMM CXXDEBUGFLAGS = -g
-
- VNCUNIXDIR = VncUnixDir
- VNCCOMMONDIR = VncCommonDir
- VNCINCLUDE = -I$(VNCCOMMONDIR) -I$(VNCUNIXDIR)/vncconfig
-
-#define CplusplusSource
-
-#if DoLoadableServer
-#define IHaveSubdirs
-#endif
-
-#include <Server.tmpl>
-
-#if DoLoadableServer
- MODULE_SUBDIRS = module
-#endif
- SRCS = vncExtInit.cc vncHooks.cc XserverDesktop.cc
- OBJS = vncExtInit.o vncHooks.o XserverDesktop.o
- INCLUDES = -I../include -I$(EXTINCSRC) -I$(XINCLUDESRC) -I$(FONTINCSRC) \
- -I../render $(VNCINCLUDE)
-#if defined(XFree86Version) && XFree86Version >= 4000
- VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP
-#endif
-#if defined(ProjectX) && (ProjectX >= 604)
- VNCDEFINES = -DGC_HAS_COMPOSITE_CLIP
-#endif
- DEFINES = $(STD_DEFINES) $(VNCDEFINES) -UXFree86LOADER
-
-#define IHaveSubdirs
-SUBDIRS = Xvnc $(MODULE_SUBDIRS)
-
-NormalLibraryTarget(vnc,$(OBJS))
-LintLibraryTarget(vnc,$(SRCS))
-NormalLintTarget($(SRCS))
-
-NormalLibraryObjectRule()
-NormalCplusplusObjectRule()
-
-
-MakeSubdirs($(SUBDIRS))
-DependSubdirs($(SUBDIRS))
-
-DependTarget()
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __REGIONHELPER_H__
-#define __REGIONHELPER_H__
-
-// RegionHelper is a class which helps in using X server regions by
-// automatically freeing them in the destructor. It also fixes a problem with
-// REGION_INIT when given an empty rectangle.
-
-// REGION_NULL was introduced in the Xorg tree as the way to initialise an
-// empty region. If it's not already defined do it the old way. Note that the
-// old way causes a segfault in the new tree...
-#ifndef REGION_NULL
-#define REGION_NULL(pScreen,pReg) REGION_INIT(pScreen,pReg,NullBox,0)
-#endif
-
-class RegionHelper {
-public:
-
- // constructor from a single rect
- RegionHelper(ScreenPtr pScreen_, BoxPtr rect, int size)
- : pScreen(pScreen_), reg(0)
- {
- init(rect, size);
- }
-
- // constructor from an existing X server region
- RegionHelper(ScreenPtr pScreen_, RegionPtr pRegion)
- : pScreen(pScreen_), reg(®Rec)
- {
- REGION_NULL(pScreen, reg);
- REGION_COPY(pScreen, reg, pRegion);
- }
-
- // constructor from an array of rectangles
- RegionHelper(ScreenPtr pScreen_, int nrects, xRectanglePtr rects,
- int ctype=CT_NONE)
- : pScreen(pScreen_)
- {
- reg = RECTS_TO_REGION(pScreen, nrects, rects, ctype);
- }
-
- // constructor for calling init() later
- RegionHelper(ScreenPtr pScreen_) : pScreen(pScreen_), reg(0) {
- }
-
- void init(BoxPtr rect, int size) {
- reg = ®Rec;
- if (!rect || (rect && (rect->x2 == rect->x1 || rect->y2 == rect->y1))) {
- REGION_NULL(pScreen, reg);
- } else {
- REGION_INIT(pScreen, reg, rect, size);
- }
- }
-
- // destructor frees as appropriate
- ~RegionHelper() {
- if (reg == ®Rec) {
- REGION_UNINIT(pScreen, reg);
- } else if (reg) {
- REGION_DESTROY(pScreen, reg);
- }
- }
- ScreenPtr pScreen;
- RegionRec regRec;
- RegionPtr reg;
-};
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// XserverDesktop.cxx
-//
-
-#include <stdio.h>
-#include <strings.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/utsname.h>
-#include <network/TcpSocket.h>
-#include <rfb/Exception.h>
-#include <rfb/VNCServerST.h>
-#include <rfb/HTTPServer.h>
-#include <rfb/LogWriter.h>
-#include <rfb/Configuration.h>
-#include "XserverDesktop.h"
-#include "vncExtInit.h"
-
-extern "C" {
-#define public c_public
-#define class c_class
-
- // windowTable is in globals.h in XFree 4, but not in XFree 3 unfortunately
-extern WindowPtr *WindowTable;
-extern char *display;
-
-#include "inputstr.h"
-#include "servermd.h"
-#include "colormapst.h"
-#include "resource.h"
-#include "cursorstr.h"
-#include "windowstr.h"
-#define XK_CYRILLIC
-#include "keysym.h"
-#undef public
-#undef class
-}
-
-using namespace rfb;
-using namespace network;
-
-static LogWriter vlog("XserverDesktop");
-
-rfb::IntParameter deferUpdateTime("DeferUpdate",
- "Time in milliseconds to defer updates",40);
-
-rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
- "Always reset the defer update timer on every change",false);
-
-IntParameter queryConnectTimeout("QueryConnectTimeout",
- "Number of seconds to show the Accept Connection dialog before "
- "rejecting the connection",
- 10);
-
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
-
-static rdr::U8 reverseBits[] = {
- 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
-};
-
-
-class FileHTTPServer : public rfb::HTTPServer {
-public:
- FileHTTPServer(XserverDesktop* d) : desktop(d) {}
- virtual ~FileHTTPServer() {}
-
- virtual rdr::InStream* getFile(const char* name, const char** contentType,
- int* contentLength, time_t* lastModified)
- {
- if (name[0] != '/' || strstr(name, "..") != 0) {
- vlog.info("http request was for invalid file name");
- return 0;
- }
-
- if (strcmp(name, "/") == 0) name = "/index.vnc";
-
- CharArray httpDirStr(httpDir.getData());
- CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
- sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
- int fd = open(fname.buf, O_RDONLY);
- if (fd < 0) return 0;
- rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
- *contentType = guessContentType(name, *contentType);
- if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
- is = new rdr::SubstitutingInStream(is, desktop, 20);
- *contentType = "text/html";
- } else {
- struct stat st;
- if (fstat(fd, &st) == 0) {
- *contentLength = st.st_size;
- *lastModified = st.st_mtime;
- }
- }
- return is;
- }
-
- XserverDesktop* desktop;
-};
-
-
-XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
- network::TcpListener* listener_,
- network::TcpListener* httpListener_,
- const char* name, void* fbptr)
- : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0),
- server(0), httpServer(0),
- listener(listener_), httpListener(httpListener_),
- cmap(0), deferredUpdateTimerSet(false),
- grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
- oldButtonMask(0),
- queryConnectId(0)
-{
- int i;
- format.depth = pScreen->rootDepth;
- for (i = 0; i < screenInfo.numPixmapFormats; i++) {
- if (screenInfo.formats[i].depth == format.depth) {
- format.bpp = screenInfo.formats[i].bitsPerPixel;
- break;
- }
- }
- if (i == screenInfo.numPixmapFormats) {
- fprintf(stderr,"no pixmap format for root depth???\n");
- abort();
- }
- format.bigEndian = (screenInfo.imageByteOrder == MSBFirst);
-
- VisualPtr vis;
- for (i = 0; i < pScreen->numVisuals; i++) {
- if (pScreen->visuals[i].vid == pScreen->rootVisual) {
- vis = &pScreen->visuals[i];
- break;
- }
- }
- if (i == pScreen->numVisuals) {
- fprintf(stderr,"no visual rec for root visual???\n");
- abort();
- }
- format.trueColour = (vis->c_class == TrueColor);
- if (!format.trueColour && format.bpp != 8)
- throw rfb::Exception("X server uses unsupported visual");
- format.redShift = ffs(vis->redMask) - 1;
- format.greenShift = ffs(vis->greenMask) - 1;
- format.blueShift = ffs(vis->blueMask) - 1;
- format.redMax = vis->redMask >> format.redShift;
- format.greenMax = vis->greenMask >> format.greenShift;
- format.blueMax = vis->blueMask >> format.blueShift;
-
- width_ = pScreen->width;
- height_ = pScreen->height;
- if (fbptr)
- data = (rdr::U8*)fbptr;
- else
- data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)];
- colourmap = this;
-
- serverReset(pScreen);
-
- server = new VNCServerST(name, this);
- server->setPixelBuffer(this);
- server->setQueryConnectionHandler(this);
-
- if (httpListener)
- httpServer = new FileHTTPServer(this);
-}
-
-XserverDesktop::~XserverDesktop()
-{
- if (!directFbptr)
- delete [] data;
- TimerFree(deferredUpdateTimer);
- TimerFree(dummyTimer);
- delete httpServer;
- delete server;
-}
-
-void XserverDesktop::serverReset(ScreenPtr pScreen_)
-{
- pScreen = pScreen_;
- XID* ids = new XID[pScreen->maxInstalledCmaps];
- int nmaps = (*pScreen->ListInstalledColormaps)(pScreen, ids);
- cmap = (ColormapPtr)LookupIDByType(ids[0], RT_COLORMAP);
- delete [] ids;
-}
-
-char* XserverDesktop::substitute(const char* varName)
-{
- if (strcmp(varName, "$$") == 0) {
- return rfb::strDup("$");
- }
- if (strcmp(varName, "$PORT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", listener ? listener->getMyPort() : 0);
- return str;
- }
- if (strcmp(varName, "$WIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", width());
- return str;
- }
- if (strcmp(varName, "$HEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", height());
- return str;
- }
- if (strcmp(varName, "$APPLETWIDTH") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", width());
- return str;
- }
- if (strcmp(varName, "$APPLETHEIGHT") == 0) {
- char* str = new char[10];
- sprintf(str, "%d", height() + 32);
- return str;
- }
- if (strcmp(varName, "$DESKTOP") == 0) {
- return rfb::strDup(server->getName());
- }
- if (strcmp(varName, "$DISPLAY") == 0) {
- struct utsname uts;
- uname(&uts);
- char* str = new char[256];
- strncat(str, uts.nodename, 240);
- strcat(str, ":");
- strncat(str, display, 10);
- return str;
- }
- if (strcmp(varName, "$USER") == 0) {
- struct passwd* user = getpwuid(getuid());
- return rfb::strDup(user ? user->pw_name : "?");
- }
- return 0;
-}
-
-rfb::VNCServerST::queryResult
-XserverDesktop::queryConnection(network::Socket* sock,
- const char* userName,
- char** reason) {
- if (queryConnectId) {
- *reason = strDup("Another connection is currently being queried.");
- return rfb::VNCServerST::REJECT;
- }
- queryConnectAddress.replaceBuf(sock->getPeerAddress());
- if (!userName)
- userName = "(anonymous)";
- queryConnectUsername.replaceBuf(strDup(userName));
- queryConnectId = sock;
- vncQueryConnect(this, sock);
- return rfb::VNCServerST::PENDING;
-}
-
-
-void XserverDesktop::setColormap(ColormapPtr cmap_)
-{
- if (cmap != cmap_) {
- cmap = cmap_;
- setColourMapEntries(0, 0);
- }
-}
-
-void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
- xColorItem* pdef)
-{
- if (cmap != pColormap || ndef <= 0) return;
-
- int first = pdef[0].pixel;
- int n = 1;
-
- for (int i = 1; i < ndef; i++) {
- if (first + n == pdef[i].pixel) {
- n++;
- } else {
- setColourMapEntries(first, n);
- first = pdef[i].pixel;
- n = 1;
- }
- }
- setColourMapEntries(first, n);
-}
-
-void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
-{
- try {
- server->setColourMapEntries(firstColour, nColours);
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
- }
-}
-
-void XserverDesktop::bell()
-{
- server->bell();
-}
-
-void XserverDesktop::serverCutText(const char* str, int len)
-{
- try {
- server->serverCutText(str, len);
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::serverCutText: %s",e.str());
- }
-}
-
-void XserverDesktop::setCursor(CursorPtr cursor)
-{
- try {
- int w = cursor->bits->width;
- int h = cursor->bits->height;
- rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)];
-
- xColorItem fg, bg;
- fg.red = cursor->foreRed;
- fg.green = cursor->foreGreen;
- fg.blue = cursor->foreBlue;
- FakeAllocColor(cmap, &fg);
- bg.red = cursor->backRed;
- bg.green = cursor->backGreen;
- bg.blue = cursor->backBlue;
- FakeAllocColor(cmap, &bg);
- FakeFreeColor(cmap, fg.pixel);
- FakeFreeColor(cmap, bg.pixel);
-
- int xMaskBytesPerRow = BitmapBytePad(w);
-
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- int byte = y * xMaskBytesPerRow + x / 8;
-#if (BITMAP_BIT_ORDER == MSBFirst)
- int bit = 7 - x % 8;
-#else
- int bit = x % 8;
-#endif
- switch (getPF().bpp) {
- case 8:
- ((rdr::U8*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- case 16:
- ((rdr::U16*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- case 32:
- ((rdr::U32*)cursorData)[y * w + x]
- = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
- break;
- }
- }
- }
-
- int rfbMaskBytesPerRow = (w + 7) / 8;
-
- rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h];
-
- for (int j = 0; j < h; j++) {
- for (int i = 0; i < rfbMaskBytesPerRow; i++)
-#if (BITMAP_BIT_ORDER == MSBFirst)
- cursorMask[j * rfbMaskBytesPerRow + i]
- = cursor->bits->mask[j * xMaskBytesPerRow + i];
-#else
- cursorMask[j * rfbMaskBytesPerRow + i]
- = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]];
-#endif
- }
-
- server->setCursor(cursor->bits->width, cursor->bits->height,
- Point(cursor->bits->xhot, cursor->bits->yhot),
- cursorData, cursorMask);
- server->tryUpdate();
- delete [] cursorData;
- delete [] cursorMask;
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::setCursor: %s",e.str());
- }
-}
-
-static void printRegion(RegionPtr reg)
-{
- int nrects = REGION_NUM_RECTS(reg);
-
- fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects,
- (REGION_EXTENTS(pScreen,reg))->x1,
- (REGION_EXTENTS(pScreen,reg))->y1,
- (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1,
- (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1);
-
- for (int i = 0; i < nrects; i++) {
- fprintf(stderr," rect %3d,%3d %3dx%3d\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);
- }
-}
-
-CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
- CARD32 now, pointer arg)
-{
- XserverDesktop* desktop = (XserverDesktop*)arg;
- desktop->deferredUpdateTimerSet = false;
- try {
- desktop->server->tryUpdate();
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
- }
- return 0;
-}
-
-void XserverDesktop::deferUpdate()
-{
- if (deferUpdateTime != 0) {
- if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
- deferredUpdateTimerSet = true;
- deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
- deferUpdateTime,
- deferredUpdateTimerCallback, this);
- }
- } else {
- server->tryUpdate();
- }
-}
-
-void XserverDesktop::add_changed(RegionPtr reg)
-{
- if (ignoreHooks_) return;
- if (grabbing) return;
- try {
- rfb::Region rfbReg;
- rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg),
- REGION_NUM_RECTS(reg),
- (ShortRect*)REGION_RECTS(reg));
- server->add_changed(rfbReg);
- deferUpdate();
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::add_changed: %s",e.str());
- }
-}
-
-void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
-{
- if (ignoreHooks_) return;
- if (grabbing) return;
- try {
- rfb::Region rfbReg;
- rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst),
- REGION_NUM_RECTS(dst),
- (ShortRect*)REGION_RECTS(dst));
- server->add_copied(rfbReg, rfb::Point(dx, dy));
- deferUpdate();
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::add_copied: %s",e.str());
- }
-}
-
-void XserverDesktop::positionCursor()
-{
- if (!cursorPos.equals(oldCursorPos)) {
- oldCursorPos = cursorPos;
- (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE);
- server->setCursorPos(cursorPos);
- server->tryUpdate();
- }
-}
-
-void XserverDesktop::blockHandler(fd_set* fds)
-{
- try {
- ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
- if (screenWithCursor == pScreen) {
- int x, y;
- GetSpritePosition(&x, &y);
- if (x != cursorPos.x || y != cursorPos.y) {
- cursorPos = oldCursorPos = Point(x, y);
- server->setCursorPos(cursorPos);
- server->tryUpdate();
- }
- }
-
- if (listener)
- FD_SET(listener->getFd(), fds);
- if (httpListener)
- FD_SET(httpListener->getFd(), fds);
-
- std::list<Socket*> sockets;
- server->getSockets(&sockets);
- std::list<Socket*>::iterator i;
- for (i = sockets.begin(); i != sockets.end(); i++) {
- int fd = (*i)->getFd();
- if ((*i)->isShutdown()) {
- vlog.debug("client gone, sock %d",fd);
- server->removeSocket(*i);
- vncClientGone(fd);
- delete (*i);
- } else {
- FD_SET(fd, fds);
- }
- }
- if (httpServer) {
- httpServer->getSockets(&sockets);
- for (i = sockets.begin(); i != sockets.end(); i++) {
- int fd = (*i)->getFd();
- if ((*i)->isShutdown()) {
- vlog.debug("http client gone, sock %d",fd);
- httpServer->removeSocket(*i);
- delete (*i);
- } else {
- FD_SET(fd, fds);
- }
- }
- }
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::blockHandler: %s",e.str());
- }
-}
-
-static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) {
- return 0;
-}
-
-void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
-{
- try {
- if (nfds >= 1) {
-
- if (listener) {
- if (FD_ISSET(listener->getFd(), fds)) {
- FD_CLR(listener->getFd(), fds);
- Socket* sock = listener->accept();
- server->addSocket(sock);
- vlog.debug("new client, sock %d",sock->getFd());
- }
- }
-
- if (httpListener) {
- if (FD_ISSET(httpListener->getFd(), fds)) {
- FD_CLR(httpListener->getFd(), fds);
- Socket* sock = httpListener->accept();
- httpServer->addSocket(sock);
- vlog.debug("new http client, sock %d",sock->getFd());
- }
- }
-
- std::list<Socket*> sockets;
- server->getSockets(&sockets);
- std::list<Socket*>::iterator i;
- for (i = sockets.begin(); i != sockets.end(); i++) {
- int fd = (*i)->getFd();
- if (FD_ISSET(fd, fds)) {
- FD_CLR(fd, fds);
- server->processSocketEvent(*i);
- }
- }
-
- if (httpServer) {
- httpServer->getSockets(&sockets);
- for (i = sockets.begin(); i != sockets.end(); i++) {
- int fd = (*i)->getFd();
- if (FD_ISSET(fd, fds)) {
- FD_CLR(fd, fds);
- httpServer->processSocketEvent(*i);
- }
- }
- }
-
- positionCursor();
- }
-
- int timeout = server->checkTimeouts();
- if (timeout > 0) {
- // set a dummy timer just so we are guaranteed be called again next time.
- dummyTimer = TimerSet(dummyTimer, 0, timeout,
- dummyTimerCallback, 0);
- }
-
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::wakeupHandler: %s",e.str());
- }
-}
-
-void XserverDesktop::addClient(Socket* sock, bool reverse)
-{
- vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
- server->addSocket(sock, reverse);
-}
-
-void XserverDesktop::disconnectClients()
-{
- vlog.debug("disconnecting all clients");
- return server->closeClients("Disconnection from server end");
-}
-
-
-int XserverDesktop::getQueryTimeout(void* opaqueId,
- const char** address,
- const char** username)
-{
- if (opaqueId && queryConnectId == opaqueId) {
- vlog.info("address=%s, username=%s, timeout=%d",
- queryConnectAddress.buf, queryConnectUsername.buf,
- (int)queryConnectTimeout);
- if (address) *address = queryConnectAddress.buf;
- if (username) *username = queryConnectUsername.buf;
- return queryConnectTimeout;
- }
- return 0;
-}
-
-void XserverDesktop::approveConnection(void* opaqueId, bool accept,
- const char* rejectMsg)
-{
- if (queryConnectId == opaqueId) {
- server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
- queryConnectId = 0;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-// SDesktop callbacks
-
-
-void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
-{
- xEvent ev;
- DevicePtr dev = LookupPointerDevice();
-
- // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
- // for S3), so we delay calling it until positionCursor() is called at the
- // end of processing a load of RFB.
- //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
-
- NewCurrentScreen(pScreen, pos.x, pos.y);
-
- ev.u.u.type = MotionNotify;
- ev.u.u.detail = 0;
- ev.u.keyButtonPointer.rootX = pos.x;
- ev.u.keyButtonPointer.rootY = pos.y;
- ev.u.keyButtonPointer.time = GetTimeInMillis();
-
- if (!pos.equals(cursorPos))
- (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
-
- for (int i = 0; i < 5; i++) {
- if ((buttonMask ^ oldButtonMask) & (1<<i)) {
- // Do not use the pointer mapping. Treat VNC buttons as logical
- // buttons.
- ev.u.u.detail = i + 1;
- ev.u.u.type = (buttonMask & (1<<i)) ? ButtonPress : ButtonRelease;
- (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
- }
- }
-
- cursorPos = pos;
- oldButtonMask = buttonMask;
-}
-
-void XserverDesktop::clientCutText(const char* str, int len)
-{
- vncClientCutText(str, len);
-}
-
-void XserverDesktop::grabRegion(const rfb::Region& region)
-{
- if (directFbptr) return;
- if (!pScreen->GetImage) {
- vlog.error("VNC error: pScreen->GetImage == 0");
- return;
- }
-
- grabbing = true;
-
- int bytesPerPixel = format.bpp/8;
- int bytesPerRow = pScreen->width * bytesPerPixel;
-
- std::vector<rfb::Rect> rects;
- std::vector<rfb::Rect>::iterator i;
- region.get_rects(&rects);
- for (i = rects.begin(); i != rects.end(); i++) {
- for (int y = i->tl.y; y < i->br.y; y++) {
- (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum],
- i->tl.x, y, i->width(), 1,
- ZPixmap, (unsigned long)~0L,
- ((char*)data
- + y * bytesPerRow + i->tl.x * bytesPerPixel));
- }
- }
- grabbing = false;
-}
-
-void XserverDesktop::lookup(int index, int* r, int* g, int* b)
-{
- if ((cmap->c_class | DynamicClass) == DirectColor) {
- VisualPtr v = cmap->pVisual;
- *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red;
- *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
- *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
- } else {
- EntryPtr pent;
- pent = (EntryPtr)&cmap->red[index];
- 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;
- }
- }
-}
-
-//
-// Keyboard handling
-//
-
-#define IS_PRESSED(keyc, keycode) \
- ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
-
-// ModifierState is a class which helps simplify generating a "fake" press
-// or release of shift, ctrl, alt, etc. An instance of the class is created
-// for every modifier which may need to be pressed or released. Then either
-// press() or release() may be called to make sure that the corresponding keys
-// are in the right state. The destructor of the class automatically reverts
-// to the previous state. Each modifier may have multiple keys associated with
-// it, so in the case of a fake release, this may involve releasing more than
-// one key.
-
-class ModifierState {
-public:
- ModifierState(DeviceIntPtr dev_, int modIndex_)
- : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
- {
- }
- ~ModifierState() {
- for (int i = 0; i < nKeys; i++)
- generateXKeyEvent(keys[i], !pressed);
- delete [] keys;
- }
- void press() {
- KeyClassPtr keyc = dev->key;
- if (!(keyc->state & (1<<modIndex))) {
- tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
- true);
- pressed = true;
- }
- }
- void release() {
- KeyClassPtr keyc = dev->key;
- if (keyc->state & (1<<modIndex)) {
- for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
- int keycode
- = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
- if (keycode && IS_PRESSED(keyc, keycode))
- tempKeyEvent(keycode, false);
- }
- }
- }
-private:
- void tempKeyEvent(int keycode, bool down) {
- if (keycode) {
- if (!keys) keys = new int[dev->key->maxKeysPerModifier];
- keys[nKeys++] = keycode;
- generateXKeyEvent(keycode, down);
- }
- }
- void generateXKeyEvent(int keycode, bool down) {
- xEvent ev;
- ev.u.u.type = down ? KeyPress : KeyRelease;
- ev.u.u.detail = keycode;
- ev.u.keyButtonPointer.time = GetTimeInMillis();
- (*dev->c_public.processInputProc)(&ev, dev, 1);
- vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
- }
- DeviceIntPtr dev;
- int modIndex;
- int nKeys;
- int* keys;
- bool pressed;
-};
-
-
-// altKeysym is a table of alternative keysyms which have the same meaning.
-
-struct altKeysym_t {
- KeySym a, b;
-};
-
-altKeysym_t altKeysym[] = {
- { XK_Shift_L, XK_Shift_R },
- { XK_Control_L, XK_Control_R },
- { XK_Meta_L, XK_Meta_R },
- { XK_Alt_L, XK_Alt_R },
- { XK_Super_L, XK_Super_R },
- { XK_Hyper_L, XK_Hyper_R },
- { XK_KP_Space, XK_space },
- { XK_KP_Tab, XK_Tab },
- { XK_KP_Enter, XK_Return },
- { XK_KP_F1, XK_F1 },
- { XK_KP_F2, XK_F2 },
- { XK_KP_F3, XK_F3 },
- { XK_KP_F4, XK_F4 },
- { XK_KP_Home, XK_Home },
- { XK_KP_Left, XK_Left },
- { XK_KP_Up, XK_Up },
- { XK_KP_Right, XK_Right },
- { XK_KP_Down, XK_Down },
- { XK_KP_Page_Up, XK_Page_Up },
- { XK_KP_Page_Down, XK_Page_Down },
- { XK_KP_End, XK_End },
- { XK_KP_Begin, XK_Begin },
- { XK_KP_Insert, XK_Insert },
- { XK_KP_Delete, XK_Delete },
- { XK_KP_Equal, XK_equal },
- { XK_KP_Multiply, XK_asterisk },
- { XK_KP_Add, XK_plus },
- { XK_KP_Separator, XK_comma },
- { XK_KP_Subtract, XK_minus },
- { XK_KP_Decimal, XK_period },
- { XK_KP_Divide, XK_slash },
- { XK_KP_0, XK_0 },
- { XK_KP_1, XK_1 },
- { XK_KP_2, XK_2 },
- { XK_KP_3, XK_3 },
- { XK_KP_4, XK_4 },
- { XK_KP_5, XK_5 },
- { XK_KP_6, XK_6 },
- { XK_KP_7, XK_7 },
- { XK_KP_8, XK_8 },
- { XK_KP_9, XK_9 },
-};
-
-// keyEvent() - work out the best keycode corresponding to the keysym sent by
-// the viewer. This is non-trivial because we can't assume much about the
-// local keyboard layout. We must also find out which column of the keyboard
-// mapping the keysym is in, and alter the shift state appropriately. Column 0
-// means both shift and "mode_switch" (AltGr) must be released, column 1 means
-// shift must be pressed and mode_switch released, column 2 means shift must be
-// released and mode_switch pressed, and column 3 means both shift and
-// mode_switch must be pressed.
-
-void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
-{
- if (keysym == XK_Caps_Lock) {
- vlog.debug("Ignoring caps lock");
- return;
- }
- DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice();
- KeyClassPtr keyc = dev->key;
- KeySymsPtr keymap = &keyc->curKeySyms;
-
- // find which modifier Mode_switch is on.
- int modeSwitchMapIndex = 0;
- for (int i = 3; i < 8; i++) {
- for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
- int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
- for (int j = 0; j < keymap->mapWidth; j++) {
- if (keycode != 0 &&
- keymap->map[(keycode - keymap->minKeyCode)
- * keymap->mapWidth + j] == XK_Mode_switch)
- {
- modeSwitchMapIndex = i;
- break;
- }
- }
- }
- }
-
- int col = 0;
- if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
- if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
-
- int kc = KeysymToKeycode(keymap, keysym, &col);
-
- // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a
- // local shifted Tab regardless of what the "shifted Tab" keysym is on the
- // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
- // keysym, and quite possibly some others too). We never get ISO_Left_Tab
- // here because it's already been translated in VNCSConnectionST.
- if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
- col |= 1;
-
- if (kc == 0) {
- // Not a direct match in the local keyboard mapping. Check for alternative
- // keysyms with the same meaning.
- for (int i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
- if (keysym == altKeysym[i].a)
- kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
- else if (keysym == altKeysym[i].b)
- kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
- if (kc) break;
- }
- }
-
- if (kc == 0) {
- // Last resort - dynamically add a new key to the keyboard mapping.
- for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
- if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
- keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
- col = 0;
- SendMappingNotify(MappingKeyboard, kc, 1, serverClient);
- vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
- break;
- }
- }
- if (kc < keymap->minKeyCode) {
- vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
- return;
- }
- }
-
- // See if it's a modifier key. If so, then don't do any auto-repeat, because
- // the X server will translate each press into a release followed by a press.
- for (int i = 0; i < 8; i++) {
- for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
- if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
- IS_PRESSED(keyc,kc) && down)
- return;
- }
- }
-
- ModifierState shift(dev, ShiftMapIndex);
- ModifierState modeSwitch(dev, modeSwitchMapIndex);
- if (down) {
- if (col & 1)
- shift.press();
- else
- shift.release();
- if (modeSwitchMapIndex) {
- if (col & 2)
- modeSwitch.press();
- else
- modeSwitch.release();
- }
- }
- vlog.debug("keycode %d %s", kc, down ? "down" : "up");
- xEvent ev;
- ev.u.u.type = down ? KeyPress : KeyRelease;
- ev.u.u.detail = kc;
- ev.u.keyButtonPointer.time = GetTimeInMillis();
- (*dev->c_public.processInputProc)(&ev, dev, 1);
-}
-
-
-void XConvertCase(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;
- }
-}
-
-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
-{
- register int per = keymap->mapWidth;
- register KeySym *syms;
- KeySym lsym, usym;
-
- if ((col < 0) || ((col >= per) && (col > 3)) ||
- (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
- return NoSymbol;
-
- syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
- if (col < 4) {
- if (col > 1) {
- while ((per > 2) && (syms[per - 1] == NoSymbol))
- per--;
- if (per < 3)
- col -= 2;
- }
- if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
- XConvertCase(syms[col&~1], &lsym, &usym);
- if (!(col & 1))
- return lsym;
- // I'm commenting out this logic because it's incorrect even though it
- // was copied from the Xlib sources. The X protocol book quite clearly
- // states that where a group consists of element 1 being a non-alphabetic
- // keysym and element 2 being NoSymbol that you treat the second element
- // as being the same as the first. This also tallies with the behaviour
- // produced by the installed Xlib on my linux box (I believe this is
- // because it uses some XKB code rather than the original Xlib code -
- // compare XKBBind.c with KeyBind.c in lib/X11).
- // else if (usym == lsym)
- // return NoSymbol;
- else
- return usym;
- }
- }
- return syms[col];
-}
-
-// KeysymToKeycode() - find the keycode and column corresponding to the given
-// keysym. The value of col passed in should be the column determined from the
-// current shift state. If the keysym can be found in that column we prefer
-// that to finding it in a different column (which would require fake events to
-// alter the shift state).
-
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
-{
- register int i, j;
-
- j = *col;
- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
- if (KeyCodetoKeySym(keymap, i, j) == ks)
- return i;
- }
-
- for (j = 0; j < keymap->mapWidth; j++) {
- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
- if (KeyCodetoKeySym(keymap, i, j) == ks) {
- *col = j;
- return i;
- }
- }
- }
- return 0;
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-//
-// XserverDesktop.h
-//
-
-#ifndef __XSERVERDESKTOP_H__
-#define __XSERVERDESKTOP_H__
-
-#include <rfb/SDesktop.h>
-#include <rfb/HTTPServer.h>
-#include <rfb/PixelBuffer.h>
-#include <rfb/Configuration.h>
-#include <rfb/VNCServerST.h>
-#include <rdr/SubstitutingInStream.h>
-
-extern "C" {
-#define class c_class;
-#include <scrnintstr.h>
-#include <os.h>
-#undef class
-}
-
-namespace rfb {
- class VNCServerST;
-}
-
-namespace network { class TcpListener; class Socket; }
-
-class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
- public rfb::ColourMap, public rdr::Substitutor,
- public rfb::VNCServerST::QueryConnectionHandler {
-public:
-
- XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener,
- network::TcpListener* httpListener_,
- const char* name, void* fbptr);
- virtual ~XserverDesktop();
-
- // methods called from X server code
- void serverReset(ScreenPtr pScreen);
- void setColormap(ColormapPtr cmap);
- void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
- void bell();
- void serverCutText(const char* str, int len);
- void setCursor(CursorPtr cursor);
- void add_changed(RegionPtr reg);
- void add_copied(RegionPtr dst, int dx, int dy);
- void positionCursor();
- void ignoreHooks(bool b) { ignoreHooks_ = b; }
- void blockHandler(fd_set* fds);
- void wakeupHandler(fd_set* fds, int nfds);
- void addClient(network::Socket* sock, bool reverse);
- void disconnectClients();
-
- // QueryConnect methods called from X server code
- // getQueryTimeout()
- // Returns the timeout associated with a particular
- // connection, identified by an opaque Id passed to the
- // X code earlier. Also optionally gets the address and
- // name associated with that connection.
- // Returns zero if the Id is not recognised.
- int getQueryTimeout(void* opaqueId,
- const char** address=0,
- const char** username=0);
-
- // approveConnection()
- // Used by X server code to supply the result of a query.
- void approveConnection(void* opaqueId, bool accept,
- const char* rejectMsg=0);
-
- // rfb::SDesktop callbacks
- virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
- virtual void keyEvent(rdr::U32 key, bool down);
- virtual void clientCutText(const char* str, int len);
- virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
-
- // rfb::PixelBuffer callbacks
- virtual void grabRegion(const rfb::Region& r);
-
- // rfb::ColourMap callbacks
- virtual void lookup(int index, int* r, int* g, int* b);
-
- // rdr::Substitutor callback
- virtual char* substitute(const char* varName);
-
- // rfb::VNCServerST::QueryConnectionHandler callback
- virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
- const char* userName,
- char** reason);
-
-private:
- void setColourMapEntries(int firstColour, int nColours);
- static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now,
- pointer arg);
- void deferUpdate();
- ScreenPtr pScreen;
- OsTimerPtr deferredUpdateTimer, dummyTimer;
- rfb::VNCServerST* server;
- rfb::HTTPServer* httpServer;
- network::TcpListener* listener;
- network::TcpListener* httpListener;
- ColormapPtr cmap;
- bool deferredUpdateTimerSet;
- bool grabbing;
- bool ignoreHooks_;
- bool directFbptr;
- int oldButtonMask;
- rfb::Point cursorPos, oldCursorPos;
-
- void* queryConnectId;
- rfb::CharArray queryConnectAddress;
- rfb::CharArray queryConnectUsername;
-};
-#endif
+++ /dev/null
-
- VNCCOMMONDIR = VncCommonDir
- VNCINCLUDE = -I$(VNCCOMMONDIR)
- VNCLIBS = VncExtLibs
-
-#if defined(XFree86Version) && XFree86Version < 4000
- VNCDEFINES = -DNO_INIT_BACKING_STORE
-#endif
-
-#define CplusplusSource
-
-#include <Server.tmpl>
-
-#if HasShm
-SHMDEF = -DHAS_SHM
-#endif
-
-XCOMM add more architectures here as we discover them
-#if defined(HPArchitecture) || \
- (defined(SparcArchitecture) && !defined(LynxOSArchitecture)) || \
- SystemV4 || \
- defined(OSF1Architecture) || \
- defined(i386BsdArchitecture) || \
- defined(LinuxArchitecture) || \
- defined(DarwinArchitecture)
-MMAPDEF = -DHAS_MMAP
-#endif
-
-#ifdef XVendorString
-VENDORSTRING = XVendorString
-#else
-VENDORSTRING = "unknown"
-#endif
-
-#ifdef XVendorRelease
-VENDORRELEASE = XVendorRelease
-#else
-VENDORRELEASE = 0
-#endif
-
- VENDOR_STRING = -DVENDOR_STRING=\"$(VENDORSTRING)\"
- VENDOR_RELEASE = -DVENDOR_RELEASE="$(VENDORRELEASE)"
-
-#ifdef OS2Architecture
-SRCS1 = os2_stubs.c
-OBJS1 = os2_stubs.o
-#endif
-
-FBINCLUDE = -I../../fb
-
-SRCSA = xvnc.cc stubs.c $(SRCS1) miinitext.c $(SRCS2)
-
-OBJSA = xvnc.o stubs.o $(OBJS1) miinitext.o $(OBJS2)
-
-INCLUDES = -I. -I.. -I$(XBUILDINCDIR) -I$(FONTINCSRC) \
- $(FBINCLUDE) -I../../mfb -I../../mi -I../../include -I../../os \
- -I$(EXTINCSRC) -I$(XINCLUDESRC) -I$(SERVERSRC)/render $(VNCINCLUDE)
-
-DEFINES = $(OS_DEFINES) $(SHMDEF) $(MMAPDEF) $(FB_DEFINES) \
- $(VENDOR_STRING) $(VENDOR_RELEASE) $(STD_DEFINES) ServerOSDefines \
- $(VNCDEFINES) -UXFree86LOADER
-
-#if defined(XFree86Version) || defined(XorgVersion)
-/*
- * Make sure XINPUT, XF86VidTune, etc arent defined for the miinitext.o
- * used by Xvnc
- */
-EXT_DEFINES = ExtensionDefines -UXF86VIDMODE -UXFreeXDGA -UXF86MISC -UXF86DRI
-#endif
-
-
-SRCS = $(SRCSA) $(SRCSB) $(SRCSC)
-OBJS = $(OBJSA) $(OBJSB) $(OBJSC)
-
-NormalLibraryObjectRule()
-NormalLibraryTarget(xvnc,$(OBJS) buildtime.o)
-
-#ifdef OS2Architecture
-LinkSourceFile(os2_stubs.c,../xfree86/os-support/os2)
-SpecialCObjectRule(os2_stubs,$(ICONFIGFILES),-DOS2NULLSELECT)
-#endif
-
-#ifdef HasGcc
-NO_OPERATOR_NAMES = -fno-operator-names
-#endif
-LinkSourceFile(stubs.c,../../Xi)
-SpecialCplusplusObjectRule(xvnc,$(ICONFIGFILES) xvnc,$(EXT_DEFINES) $(NO_OPERATOR_NAMES))
-
-LinkSourceFile(miinitext.c,$(SERVERSRC)/mi)
-SpecialCObjectRule(miinitext,$(ICONFIGFILES),$(EXT_DEFINES) $(PAN_DEFINES) -DNO_MODULE_EXTS $(EXT_MODULE_DEFINES) -UXFree86LOADER)
-
-/* InstallManPage(Xvfb,$(MANDIR)) */
-DependTarget()
-
-buildtime.o: $(OBJS) ../LibraryTargetName(vnc) $(VNCLIBS)
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-char buildtime[] = __DATE__ " " __TIME__;
+++ /dev/null
-/* Copyright (c) 1993 X Consortium
- Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice 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 <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-#include <network/TcpSocket.h>
-#include "vncExtInit.h"
-
-extern "C" {
-#define class c_class
-#define public c_public
-#define xor c_xor
-#define and c_and
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-#include <stdio.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 "mi.h"
-#include "mibstore.h"
-#include "colormapst.h"
-#include "gcstruct.h"
-#include "input.h"
-#include "mipointer.h"
-#define new New
-#include "micmap.h"
-#undef new
-#include <sys/types.h>
-#ifdef HAS_MMAP
-#include <sys/mman.h>
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
-#endif /* HAS_MMAP */
-#include <sys/stat.h>
-#include <errno.h>
-#ifndef WIN32
-#include <sys/param.h>
-#endif
-#include <X11/XWDFile.h>
-#ifdef HAS_SHM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif /* HAS_SHM */
-#include "dix.h"
-#include "miline.h"
-#include "inputstr.h"
-#include "keysym.h"
- extern int defaultColorVisualClass;
- extern char buildtime[];
-#undef class
-#undef public
-#undef xor
-#undef and
-}
-
-#define XVNCVERSION "TightVNC 1.5 series"
-#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
- "Copyright (C) 2000-2006 Constantin Kaplinsky\n" \
- "Copyright (C) 2004-2006 Peter Astrand, Cendio AB\n" \
- "See http://www.tightvnc.com for information on TightVNC.\n")
-
-
-extern char *display;
-extern int monitorResolution;
-
-#define VFB_DEFAULT_WIDTH 1024
-#define VFB_DEFAULT_HEIGHT 768
-#define VFB_DEFAULT_DEPTH 16
-#define VFB_DEFAULT_WHITEPIXEL 0xffff
-#define VFB_DEFAULT_BLACKPIXEL 0
-#define VFB_DEFAULT_LINEBIAS 0
-#define XWD_WINDOW_NAME_LEN 60
-
-typedef struct
-{
- int scrnum;
- int width;
- int paddedBytesWidth;
- int paddedWidth;
- int height;
- int depth;
- int bitsPerPixel;
- int sizeInBytes;
- int ncolors;
- char *pfbMemory;
- XWDColor *pXWDCmap;
- XWDFileHeader *pXWDHeader;
- Pixel blackPixel;
- Pixel whitePixel;
- unsigned int lineBias;
- CloseScreenProcPtr closeScreen;
-
-#ifdef HAS_MMAP
- int mmap_fd;
- char mmap_file[MAXPATHLEN];
-#endif
-
-#ifdef HAS_SHM
- int shmid;
-#endif
-
- Bool pixelFormatDefined;
- Bool rgbNotBgr;
- int redBits, greenBits, blueBits;
-
-} vfbScreenInfo, *vfbScreenInfoPtr;
-
-static int vfbNumScreens;
-static vfbScreenInfo vfbScreens[MAXSCREENS];
-static Bool vfbPixmapDepths[33];
-#ifdef HAS_MMAP
-static char *pfbdir = NULL;
-#endif
-typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
-static fbMemType fbmemtype = NORMAL_MEMORY_FB;
-static char needswap = 0;
-static int lastScreen = -1;
-static Bool Render = TRUE;
-
-static bool displaySpecified = false;
-static bool wellKnownSocketsCreated = false;
-static char displayNumStr[16];
-
-#define swapcopy16(_dst, _src) \
- if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
- else _dst = _src;
-
-#define swapcopy32(_dst, _src) \
- if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
- else _dst = _src;
-
-
-static void
-vfbInitializePixmapDepths(void)
-{
- int i;
- vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
- for (i = 2; i <= 32; i++)
- vfbPixmapDepths[i] = FALSE;
-}
-
-static void
-vfbInitializeDefaultScreens(void)
-{
- int i;
-
- for (i = 0; i < MAXSCREENS; i++)
- {
- vfbScreens[i].scrnum = i;
- vfbScreens[i].width = VFB_DEFAULT_WIDTH;
- vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
- vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
- vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
- vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
- vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
- vfbScreens[i].pixelFormatDefined = FALSE;
- vfbScreens[i].pfbMemory = NULL;
- }
- vfbNumScreens = 1;
-}
-
-static int
-vfbBitsPerPixel(int depth)
-{
- if (depth == 1) return 1;
- else if (depth <= 8) return 8;
- else if (depth <= 16) return 16;
- else return 32;
-}
-
-
-extern "C" {
-
- void ddxGiveUp()
- {
- int i;
-
- /* clean up the framebuffers */
-
- switch (fbmemtype)
- {
-#ifdef HAS_MMAP
- case MMAPPED_FILE_FB:
- for (i = 0; i < vfbNumScreens; i++)
- {
- if (-1 == unlink(vfbScreens[i].mmap_file))
- {
- perror("unlink");
- ErrorF("unlink %s failed, errno %d",
- vfbScreens[i].mmap_file, errno);
- }
- }
- break;
-#else /* HAS_MMAP */
- case MMAPPED_FILE_FB:
- break;
-#endif /* HAS_MMAP */
-
-#ifdef HAS_SHM
- case SHARED_MEMORY_FB:
- for (i = 0; i < vfbNumScreens; i++)
- {
- if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
- {
- perror("shmdt");
- ErrorF("shmdt failed, errno %d", errno);
- }
- }
- break;
-#else /* HAS_SHM */
- case SHARED_MEMORY_FB:
- break;
-#endif /* HAS_SHM */
-
- case NORMAL_MEMORY_FB:
- for (i = 0; i < vfbNumScreens; i++)
- {
- Xfree(vfbScreens[i].pXWDHeader);
- }
- break;
- }
-}
-
-void
-AbortDDX()
-{
- ddxGiveUp();
-}
-
-#ifdef __DARWIN__
-void
-DarwinHandleGUI(int argc, char *argv[])
-{
-}
-
-void GlxExtensionInit();
-void GlxWrapInitVisuals(void *procPtr);
-
-void
-DarwinGlxExtensionInit()
-{
- GlxExtensionInit();
-}
-
-void
-DarwinGlxWrapInitVisuals(
- void *procPtr)
-{
- GlxWrapInitVisuals(procPtr);
-}
-#endif
-
-void
-OsVendorInit()
-{
-}
-
-void
-OsVendorFatalError()
-{
-}
-
-void ddxBeforeReset(void)
-{
- return;
-}
-
-void
-ddxUseMsg()
-{
- ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
- ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
- VENDOR_STRING);
- ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
- ErrorF("-pixdepths list-of-int support given pixmap depths\n");
-#ifdef RENDER
- ErrorF("+/-render turn on/off RENDER extension support"
- "(default on)\n");
-#endif
- ErrorF("-linebias n adjust thin line pixelization\n");
- ErrorF("-blackpixel n pixel value for black\n");
- ErrorF("-whitepixel n pixel value for white\n");
-
-#ifdef HAS_MMAP
- ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
-#endif
-
-#ifdef HAS_SHM
- ErrorF("-shmem put framebuffers in shared memory\n");
-#endif
-
- ErrorF("-geometry WxH set screen 0's width, height\n");
- ErrorF("-depth D set screen 0's depth\n");
- ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
- ErrorF("-inetd has been launched from inetd\n");
- ErrorF("\nVNC parameters:\n");
-
- fprintf(stderr,"\n"
- "Parameters can be turned on with -<param> or off with -<param>=0\n"
- "Parameters which take a value can be specified as "
- "-<param> <value>\n"
- "Other valid forms are <param>=<value> -<param>=<value> "
- "--<param>=<value>\n"
- "Parameter names are case-insensitive. The parameters are:\n\n");
- rfb::Configuration::listParams(79, 14);
- }
-}
-
-/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
-void ddxInitGlobals(void)
-{
-}
-
-static
-bool displayNumFree(int num)
-{
- try {
- network::TcpListener l(6000+num);
- } catch (rdr::Exception& e) {
- return false;
- }
- char file[256];
- sprintf(file, "/tmp/.X%d-lock", num);
- if (access(file, F_OK) == 0) return false;
- sprintf(file, "/tmp/.X11-unix/X%d", num);
- if (access(file, F_OK) == 0) return false;
- sprintf(file, "/usr/spool/sockets/X11/%d", num);
- if (access(file, F_OK) == 0) return false;
- return true;
-}
-
-int
-ddxProcessArgument(int argc, char *argv[], int i)
-{
- static Bool firstTime = TRUE;
-
- if (firstTime)
- {
- vfbInitializeDefaultScreens();
- vfbInitializePixmapDepths();
- firstTime = FALSE;
- rfb::initStdIOLoggers();
- rfb::LogWriter::setLogParams("*:stderr:30");
- }
-
- if (argv[i][0] == ':')
- displaySpecified = true;
-
- if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
- {
- int screenNum;
- if (i + 2 >= argc) UseMsg();
- screenNum = atoi(argv[i+1]);
- if (screenNum < 0 || screenNum >= MAXSCREENS)
- {
- ErrorF("Invalid screen number %d\n", screenNum);
- UseMsg();
- }
- if (3 != sscanf(argv[i+2], "%dx%dx%d",
- &vfbScreens[screenNum].width,
- &vfbScreens[screenNum].height,
- &vfbScreens[screenNum].depth))
- {
- ErrorF("Invalid screen configuration %s\n", argv[i+2]);
- UseMsg();
- }
-
- if (screenNum >= vfbNumScreens)
- vfbNumScreens = screenNum + 1;
- lastScreen = screenNum;
- return 3;
- }
-
- if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
- {
- int depth, ret = 1;
-
- if (++i >= argc) UseMsg();
- while ((i < argc) && (depth = atoi(argv[i++])) != 0)
- {
- if (depth < 0 || depth > 32)
- {
- ErrorF("Invalid pixmap depth %d\n", depth);
- UseMsg();
- }
- vfbPixmapDepths[depth] = TRUE;
- ret++;
- }
- return ret;
- }
-
- if (strcmp (argv[i], "+render") == 0) /* +render */
- {
- Render = TRUE;
- return 1;
- }
-
- if (strcmp (argv[i], "-render") == 0) /* -render */
- {
- Render = FALSE;
- return 1;
- }
-
- if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
- {
- Pixel pix;
- if (++i >= argc) UseMsg();
- pix = atoi(argv[i]);
- if (-1 == lastScreen)
- {
- int i;
- for (i = 0; i < MAXSCREENS; i++)
- {
- vfbScreens[i].blackPixel = pix;
- }
- }
- else
- {
- vfbScreens[lastScreen].blackPixel = pix;
- }
- return 2;
- }
-
- if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
- {
- Pixel pix;
- if (++i >= argc) UseMsg();
- pix = atoi(argv[i]);
- if (-1 == lastScreen)
- {
- int i;
- for (i = 0; i < MAXSCREENS; i++)
- {
- vfbScreens[i].whitePixel = pix;
- }
- }
- else
- {
- vfbScreens[lastScreen].whitePixel = pix;
- }
- return 2;
- }
-
- if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
- {
- unsigned int linebias;
- if (++i >= argc) UseMsg();
- linebias = atoi(argv[i]);
- if (-1 == lastScreen)
- {
- int i;
- for (i = 0; i < MAXSCREENS; i++)
- {
- vfbScreens[i].lineBias = linebias;
- }
- }
- else
- {
- vfbScreens[lastScreen].lineBias = linebias;
- }
- return 2;
- }
-
-#ifdef HAS_MMAP
- if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
- {
- if (++i >= argc) UseMsg();
- pfbdir = argv[i];
- fbmemtype = MMAPPED_FILE_FB;
- return 2;
- }
-#endif /* HAS_MMAP */
-
-#ifdef HAS_SHM
- if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
- {
- fbmemtype = SHARED_MEMORY_FB;
- return 1;
- }
-#endif
-
- if (strcmp(argv[i], "-geometry") == 0)
- {
- if (++i >= argc) UseMsg();
- if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
- &vfbScreens[0].height) != 2) {
- ErrorF("Invalid geometry %s\n", argv[i]);
- UseMsg();
- }
- return 2;
- }
-
- if (strcmp(argv[i], "-depth") == 0)
- {
- if (++i >= argc) UseMsg();
- vfbScreens[0].depth = atoi(argv[i]);
- return 2;
- }
-
- if (strcmp(argv[i], "-pixelformat") == 0)
- {
- char rgbbgr[4];
- int bits1, bits2, bits3;
- if (++i >= argc) UseMsg();
- if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
- ErrorF("Invalid pixel format %s\n", argv[i]);
- UseMsg();
- }
-
-#define SET_PIXEL_FORMAT(vfbScreen) \
- (vfbScreen).pixelFormatDefined = TRUE; \
- (vfbScreen).depth = bits1 + bits2 + bits3; \
- (vfbScreen).greenBits = bits2; \
- if (strcasecmp(rgbbgr, "bgr") == 0) { \
- (vfbScreen).rgbNotBgr = FALSE; \
- (vfbScreen).redBits = bits3; \
- (vfbScreen).blueBits = bits1; \
- } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
- (vfbScreen).rgbNotBgr = TRUE; \
- (vfbScreen).redBits = bits1; \
- (vfbScreen).blueBits = bits3; \
- } else { \
- ErrorF("Invalid pixel format %s\n", argv[i]); \
- UseMsg(); \
- }
-
- if (-1 == lastScreen)
- {
- int i;
- for (i = 0; i < MAXSCREENS; i++)
- {
- SET_PIXEL_FORMAT(vfbScreens[i]);
- }
- }
- else
- {
- SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
- }
-
- return 2;
- }
-
- if (strcmp(argv[i], "-inetd") == 0)
- {
- dup2(0,3);
- vncInetdSock = 3;
- close(2);
-
- if (!displaySpecified) {
- int port = network::TcpSocket::getSockPort(vncInetdSock);
- int displayNum = port - 5900;
- if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
- for (displayNum = 1; displayNum < 100; displayNum++)
- if (displayNumFree(displayNum)) break;
-
- if (displayNum == 100)
- FatalError("Xvnc error: no free display number for -inetd");
- }
-
- display = displayNumStr;
- sprintf(displayNumStr, "%d", displayNum);
- }
-
- return 1;
- }
-
- if (rfb::Configuration::setParam(argv[i]))
- return 1;
-
- if (argv[i][0] == '-' && i+1 < argc) {
- if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
- return 2;
- }
-
- return 0;
-}
-
-#ifdef DDXTIME /* from ServerOSDefines */
-CARD32
-GetTimeInMillis()
-{
- struct timeval tp;
-
- X_GETTIMEOFDAY(&tp);
- return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
-}
-#endif
-
-static ColormapPtr InstalledMaps[MAXSCREENS];
-
-static int
-vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
-{
- /* By the time we are processing requests, we can guarantee that there
- * is always a colormap installed */
- *pmaps = InstalledMaps[pScreen->myNum]->mid;
- return (1);
-}
-
-
-static void
-vfbInstallColormap(ColormapPtr pmap)
-{
- int index = pmap->pScreen->myNum;
- ColormapPtr oldpmap = InstalledMaps[index];
-
- if (pmap != oldpmap)
- {
- int entries;
- XWDFileHeader *pXWDHeader;
- XWDColor *pXWDCmap;
- VisualPtr pVisual;
- Pixel * ppix;
- xrgb * prgb;
- xColorItem *defs;
- int i;
-
- if(oldpmap != (ColormapPtr)None)
- WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
- /* Install pmap */
- InstalledMaps[index] = pmap;
- WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
-
- entries = pmap->pVisual->ColormapEntries;
- pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
- pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
- pVisual = pmap->pVisual;
-
- swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
- swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
- swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
- swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
- swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
- swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
-
- ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
- prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
- defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
-
- for (i = 0; i < entries; i++) ppix[i] = i;
- /* XXX truecolor */
- QueryColors(pmap, entries, ppix, prgb);
-
- for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
- defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
- defs[i].red = prgb[i].red;
- defs[i].green = prgb[i].green;
- defs[i].blue = prgb[i].blue;
- defs[i].flags = DoRed|DoGreen|DoBlue;
- }
- (*pmap->pScreen->StoreColors)(pmap, entries, defs);
-
- DEALLOCATE_LOCAL(ppix);
- DEALLOCATE_LOCAL(prgb);
- DEALLOCATE_LOCAL(defs);
- }
-}
-
-static void
-vfbUninstallColormap(ColormapPtr pmap)
-{
- ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
-
- if(pmap == curpmap)
- {
- if (pmap->mid != pmap->pScreen->defColormap)
- {
- curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
- RT_COLORMAP);
- (*pmap->pScreen->InstallColormap)(curpmap);
- }
- }
-}
-
-static void
-vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
-{
- XWDColor *pXWDCmap;
- int i;
-
- if (pmap != InstalledMaps[pmap->pScreen->myNum])
- {
- return;
- }
-
- pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
-
- if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
- {
- return;
- }
-
- for (i = 0; i < ndef; i++)
- {
- if (pdefs[i].flags & DoRed)
- {
- swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
- }
- if (pdefs[i].flags & DoGreen)
- {
- swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
- }
- if (pdefs[i].flags & DoBlue)
- {
- swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
- }
- }
-}
-
-static Bool
-vfbSaveScreen(ScreenPtr pScreen, int on)
-{
- return TRUE;
-}
-
-#ifdef HAS_MMAP
-
-/* this flushes any changes to the screens out to the mmapped file */
-static void
-vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
-{
- int i;
-
- for (i = 0; i < vfbNumScreens; i++)
- {
-#ifdef MS_ASYNC
- if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
- (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
-#else
- /* silly NetBSD and who else? */
- if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
- (size_t)vfbScreens[i].sizeInBytes))
-#endif
- {
- perror("msync");
- ErrorF("msync failed, errno %d", errno);
- }
- }
-}
-
-
-static void
-vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
-{
-}
-
-
-static void
-vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
-{
-#define DUMMY_BUFFER_SIZE 65536
- char dummyBuffer[DUMMY_BUFFER_SIZE];
- int currentFileSize, writeThisTime;
-
- sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
- if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
- {
- perror("open");
- ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
- return;
- }
-
- /* Extend the file to be the proper size */
-
- bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
- for (currentFileSize = 0;
- currentFileSize < pvfb->sizeInBytes;
- currentFileSize += writeThisTime)
- {
- writeThisTime = min(DUMMY_BUFFER_SIZE,
- pvfb->sizeInBytes - currentFileSize);
- if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
- {
- perror("write");
- ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
- return;
- }
- }
-
- /* try to mmap the file */
-
- pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
- PROT_READ|PROT_WRITE,
- MAP_FILE|MAP_SHARED,
- pvfb->mmap_fd, 0);
- if (-1 == (long)pvfb->pXWDHeader)
- {
- perror("mmap");
- ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
- pvfb->pXWDHeader = NULL;
- return;
- }
-
- if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
- NULL))
- {
- pvfb->pXWDHeader = NULL;
- }
-}
-#endif /* HAS_MMAP */
-
-
-#ifdef HAS_SHM
-static void
-vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
-{
- /* create the shared memory segment */
-
- pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
- if (pvfb->shmid < 0)
- {
- perror("shmget");
- ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
- return;
- }
-
- /* try to attach it */
-
- pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
- if (-1 == (long)pvfb->pXWDHeader)
- {
- perror("shmat");
- ErrorF("shmat failed, errno %d", errno);
- pvfb->pXWDHeader = NULL;
- return;
- }
-
- ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
-}
-#endif /* HAS_SHM */
-
-
-static char *
-vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
-{
- if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
-
- pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
-
- /* Calculate how many entries in colormap. This is rather bogus, because
- * the visuals haven't even been set up yet, but we need to know because we
- * have to allocate space in the file for the colormap. The number 10
- * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
- */
-
- if (pvfb->depth <= 10)
- { /* single index colormaps */
- pvfb->ncolors = 1 << pvfb->depth;
- }
- else
- { /* decomposed colormaps */
- int nplanes_per_color_component = pvfb->depth / 3;
- if (pvfb->depth % 3) nplanes_per_color_component++;
- pvfb->ncolors = 1 << nplanes_per_color_component;
- }
-
- /* add extra bytes for XWDFileHeader, window name, and colormap */
-
- pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
- pvfb->ncolors * SIZEOF(XWDColor);
-
- pvfb->pXWDHeader = NULL;
- switch (fbmemtype)
- {
-#ifdef HAS_MMAP
- case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
-#else
- case MMAPPED_FILE_FB: break;
-#endif
-
-#ifdef HAS_SHM
- case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
-#else
- case SHARED_MEMORY_FB: break;
-#endif
-
- case NORMAL_MEMORY_FB:
- pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
- break;
- }
-
- if (pvfb->pXWDHeader)
- {
- pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
- + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
- pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
-
- return pvfb->pfbMemory;
- }
- else
- return NULL;
-}
-
-static void
-vfbWriteXWDFileHeader(ScreenPtr pScreen)
-{
- vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
- XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
- char hostname[XWD_WINDOW_NAME_LEN];
- unsigned long swaptest = 1;
- int i;
-
- needswap = *(char *) &swaptest;
-
- pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
- pXWDHeader->file_version = XWD_FILE_VERSION;
-
- pXWDHeader->pixmap_format = ZPixmap;
- pXWDHeader->pixmap_depth = pvfb->depth;
- pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
- pXWDHeader->xoffset = 0;
- pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
- pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
-#ifndef INTERNAL_VS_EXTERNAL_PADDING
- pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
- pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
- pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
-#else
- pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
- pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
- pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
-#endif
- pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
- pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
- pXWDHeader->ncolors = pvfb->ncolors;
-
- /* visual related fields are written when colormap is installed */
-
- pXWDHeader->window_x = pXWDHeader->window_y = 0;
- pXWDHeader->window_bdrwidth = 0;
-
- /* write xwd "window" name: Xvfb hostname:server.screen */
-
- if (-1 == gethostname(hostname, sizeof(hostname)))
- hostname[0] = 0;
- else
- hostname[XWD_WINDOW_NAME_LEN-1] = 0;
- sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
- pScreen->myNum);
-
- /* write colormap pixel slot values */
-
- for (i = 0; i < pvfb->ncolors; i++)
- {
- pvfb->pXWDCmap[i].pixel = i;
- }
-
- /* byte swap to most significant byte first */
-
- if (needswap)
- {
- SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
- for (i = 0; i < pvfb->ncolors; i++)
- {
- register char n;
- swapl(&pvfb->pXWDCmap[i].pixel, n);
- }
- }
-}
-
-
-static Bool
-vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
-{
- return FALSE;
-}
-
-static void
-vfbCrossScreen (ScreenPtr pScreen, Bool entering)
-{
-}
-
-static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
- return TRUE;
-}
-
-static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
- return TRUE;
-}
-
-static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
-{
-}
-
-static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
-{
-}
-
-static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
- vfbRealizeCursor,
- vfbUnrealizeCursor,
- vfbSetCursor,
- vfbMoveCursor
-};
-
-static miPointerScreenFuncRec vfbPointerCursorFuncs = {
- vfbCursorOffScreen,
- vfbCrossScreen,
- miPointerWarpCursor
-};
-
-static Bool
-vfbCloseScreen(int index, ScreenPtr pScreen)
-{
- vfbScreenInfoPtr pvfb = &vfbScreens[index];
- int i;
-
- pScreen->CloseScreen = pvfb->closeScreen;
-
- /*
- * XXX probably lots of stuff to clean. For now,
- * clear InstalledMaps[] so that server reset works correctly.
- */
- for (i = 0; i < MAXSCREENS; i++)
- InstalledMaps[i] = NULL;
-
- return pScreen->CloseScreen(index, pScreen);
-}
-
-static Bool
-vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
-{
- vfbScreenInfoPtr pvfb = &vfbScreens[index];
- int dpi = 100;
- int ret;
- char *pbits;
-
- if (monitorResolution) dpi = monitorResolution;
-
- pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
- pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
- pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
- pbits = vfbAllocateFramebufferMemory(pvfb);
- if (!pbits) return FALSE;
- vncFbptr[index] = pbits;
-
- defaultColorVisualClass
- = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
-
- ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
- dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
-
-#ifdef RENDER
- if (ret && Render)
- fbPictureInit (pScreen, 0, 0);
-#endif
-
- if (!ret) return FALSE;
-
- /* miInitializeBackingStore(pScreen); */
-
- /*
- * Circumvent the backing store that was just initialised. This amounts
- * to a truely bizarre way of initialising SaveDoomedAreas and friends.
- */
-
- pScreen->InstallColormap = vfbInstallColormap;
- pScreen->UninstallColormap = vfbUninstallColormap;
- pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
-
- pScreen->SaveScreen = vfbSaveScreen;
- pScreen->StoreColors = vfbStoreColors;
-
- miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
- FALSE);
-
- vfbWriteXWDFileHeader(pScreen);
-
- pScreen->blackPixel = pvfb->blackPixel;
- pScreen->whitePixel = pvfb->whitePixel;
-
- if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
- pvfb->pixelFormatDefined = TRUE;
- pvfb->rgbNotBgr = TRUE;
- pvfb->blueBits = pvfb->redBits = 5;
- pvfb->greenBits = 6;
- }
-
- if (pvfb->pixelFormatDefined) {
- VisualPtr vis = pScreen->visuals;
- for (int i = 0; i < pScreen->numVisuals; i++) {
- if (pvfb->rgbNotBgr) {
- vis->offsetBlue = 0;
- vis->blueMask = (1 << pvfb->blueBits) - 1;
- vis->offsetGreen = pvfb->blueBits;
- vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
- vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
- vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
- } else {
- vis->offsetRed = 0;
- vis->redMask = (1 << pvfb->redBits) - 1;
- vis->offsetGreen = pvfb->redBits;
- vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
- vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
- vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
- }
- vis++;
- }
- }
-
- ret = fbCreateDefColormap(pScreen);
-
- miSetZeroLineBias(pScreen, pvfb->lineBias);
-
- pvfb->closeScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = vfbCloseScreen;
-
-#ifndef NO_INIT_BACKING_STORE
- miInitializeBackingStore(pScreen);
- pScreen->backingStoreSupport = Always;
-#endif
-
- return ret;
-
-} /* end vfbScreenInit */
-
-
-static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
- dispatchException &= ~DE_RESET;
-}
-
-void
-InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
-{
- ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
- ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
- VENDOR_STRING);
- int i;
- int NumFormats = 0;
-
- /* initialize pixmap formats */
-
- /* must have a pixmap depth to match every screen depth */
- for (i = 0; i < vfbNumScreens; i++)
- {
- vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
- }
-
- /* RENDER needs a good set of pixmaps. */
- if (Render) {
- vfbPixmapDepths[1] = TRUE;
- vfbPixmapDepths[4] = TRUE;
- vfbPixmapDepths[8] = TRUE;
-/* vfbPixmapDepths[15] = TRUE; */
- vfbPixmapDepths[16] = TRUE;
- vfbPixmapDepths[24] = TRUE;
- vfbPixmapDepths[32] = TRUE;
- }
-
- for (i = 1; i <= 32; i++)
- {
- if (vfbPixmapDepths[i])
- {
- if (NumFormats >= MAXFORMATS)
- FatalError ("MAXFORMATS is too small for this server\n");
- screenInfo->formats[NumFormats].depth = i;
- screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
- screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
- NumFormats++;
- }
- }
-
- screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
- screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
- screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
- screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
- screenInfo->numPixmapFormats = NumFormats;
-
- /* initialize screens */
-
- for (i = 0; i < vfbNumScreens; i++)
- {
- if (-1 == AddScreen(vfbScreenInit, argc, argv))
- {
- FatalError("Couldn't add screen %d", i);
- }
- }
-
- if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
- FatalError("AddCallback failed\n");
- }
-} /* end InitOutput */
-
-#ifdef DPMSExtension
-extern "C" {
-#if NeedFunctionPrototypes
- void DPMSSet(CARD16 level)
-#else
- void DPMSSet(level)
- CARD16 level;
-#endif
- {
- return;
- }
-
- Bool DPMSSupported()
- {
- return FALSE;
- }
-}
-#endif
-
-/* this is just to get the server to link on AIX */
-#ifdef AIXV3
-int SelectWaitTime = 10000; /* usec */
-#endif
-
-Bool LegalModifier(unsigned int key, DevicePtr pDev)
-{
- return TRUE;
-}
-
-void ProcessInputEvents()
-{
- mieqProcessInputEvents();
- miPointerUpdate();
-}
-
-/* Fairly standard US PC Keyboard */
-
-#define VFB_MIN_KEY 8
-#define VFB_MAX_KEY 255
-#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
-#define KEYSYMS_PER_KEY 2
-KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
- NoSymbol, NoSymbol,
- XK_Escape, NoSymbol,
- XK_1, XK_exclam,
- XK_2, XK_at,
- XK_3, XK_numbersign,
- XK_4, XK_dollar,
- XK_5, XK_percent,
- XK_6, XK_asciicircum,
- XK_7, XK_ampersand,
- XK_8, XK_asterisk,
- XK_9, XK_parenleft,
- XK_0, XK_parenright,
- XK_minus, XK_underscore,
- XK_equal, XK_plus,
- XK_BackSpace, NoSymbol,
- XK_Tab, NoSymbol,
- XK_q, XK_Q,
- XK_w, XK_W,
- XK_e, XK_E,
- XK_r, XK_R,
- XK_t, XK_T,
- XK_y, XK_Y,
- XK_u, XK_U,
- XK_i, XK_I,
- XK_o, XK_O,
- XK_p, XK_P,
- XK_bracketleft, XK_braceleft,
- XK_bracketright, XK_braceright,
- XK_Return, NoSymbol,
- XK_Control_L, NoSymbol,
- XK_a, XK_A,
- XK_s, XK_S,
- XK_d, XK_D,
- XK_f, XK_F,
- XK_g, XK_G,
- XK_h, XK_H,
- XK_j, XK_J,
- XK_k, XK_K,
- XK_l, XK_L,
- XK_semicolon, XK_colon,
- XK_apostrophe, XK_quotedbl,
- XK_grave, XK_asciitilde,
- XK_Shift_L, NoSymbol,
- XK_backslash, XK_bar,
- XK_z, XK_Z,
- XK_x, XK_X,
- XK_c, XK_C,
- XK_v, XK_V,
- XK_b, XK_B,
- XK_n, XK_N,
- XK_m, XK_M,
- XK_comma, XK_less,
- XK_period, XK_greater,
- XK_slash, XK_question,
- XK_Shift_R, NoSymbol,
- XK_KP_Multiply, NoSymbol,
- XK_Alt_L, XK_Meta_L,
- XK_space, NoSymbol,
- /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
- XK_F1, NoSymbol,
- XK_F2, NoSymbol,
- XK_F3, NoSymbol,
- XK_F4, NoSymbol,
- XK_F5, NoSymbol,
- XK_F6, NoSymbol,
- XK_F7, NoSymbol,
- XK_F8, NoSymbol,
- XK_F9, NoSymbol,
- XK_F10, NoSymbol,
- XK_Num_Lock, XK_Pointer_EnableKeys,
- XK_Scroll_Lock, NoSymbol,
- XK_KP_Home, XK_KP_7,
- XK_KP_Up, XK_KP_8,
- XK_KP_Prior, XK_KP_9,
- XK_KP_Subtract, NoSymbol,
- XK_KP_Left, XK_KP_4,
- XK_KP_Begin, XK_KP_5,
- XK_KP_Right, XK_KP_6,
- XK_KP_Add, NoSymbol,
- XK_KP_End, XK_KP_1,
- XK_KP_Down, XK_KP_2,
- XK_KP_Next, XK_KP_3,
- XK_KP_Insert, XK_KP_0,
- XK_KP_Delete, XK_KP_Decimal,
- NoSymbol, NoSymbol,
- NoSymbol, NoSymbol,
- NoSymbol, NoSymbol,
- XK_F11, NoSymbol,
- XK_F12, NoSymbol,
- XK_Home, NoSymbol,
- XK_Up, NoSymbol,
- XK_Prior, NoSymbol,
- XK_Left, NoSymbol,
- NoSymbol, NoSymbol,
- XK_Right, NoSymbol,
- XK_End, NoSymbol,
- XK_Down, NoSymbol,
- XK_Next, NoSymbol,
- XK_Insert, NoSymbol,
- XK_Delete, NoSymbol,
- XK_KP_Enter, NoSymbol,
- XK_Control_R, NoSymbol,
- XK_Pause, XK_Break,
- XK_Print, XK_Execute,
- XK_KP_Divide, NoSymbol,
- XK_Alt_R, XK_Meta_R,
-};
-
-static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
-{
- int i;
-
- for (i = 0; i < MAP_LENGTH; i++)
- pModMap[i] = NoSymbol;
-
- for (i = 0; i < VFB_MAP_LEN; i++) {
- if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
- pModMap[i + VFB_MIN_KEY] = LockMask;
- else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
- keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
- pModMap[i + VFB_MIN_KEY] = ShiftMask;
- else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
- keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
- pModMap[i + VFB_MIN_KEY] = ControlMask;
- }
- else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
- keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
- pModMap[i + VFB_MIN_KEY] = Mod1Mask;
- }
-
- pKeySyms->minKeyCode = VFB_MIN_KEY;
- pKeySyms->maxKeyCode = VFB_MAX_KEY;
- pKeySyms->mapWidth = KEYSYMS_PER_KEY;
- pKeySyms->map = keyboardMap;
-
- return TRUE;
-}
-
-static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
-{
- if (percent > 0)
- vncBell();
-}
-
-static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
-{
- KeySymsRec keySyms;
- CARD8 modMap[MAP_LENGTH];
- DevicePtr pDev = (DevicePtr)pDevice;
-
- switch (onoff)
- {
- case DEVICE_INIT:
- GetMappings(&keySyms, modMap);
- InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
- (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
- break;
- case DEVICE_ON:
- pDev->on = TRUE;
- break;
- case DEVICE_OFF:
- pDev->on = FALSE;
- break;
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-}
-
-static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
-{
- BYTE map[6];
- DevicePtr pDev = (DevicePtr)pDevice;
-
- switch (onoff)
- {
- case DEVICE_INIT:
- map[1] = 1;
- map[2] = 2;
- map[3] = 3;
- map[4] = 4;
- map[5] = 5;
- InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
- (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
- break;
-
- case DEVICE_ON:
- pDev->on = TRUE;
- break;
-
- case DEVICE_OFF:
- pDev->on = FALSE;
- break;
-
- case DEVICE_CLOSE:
- break;
- }
- return Success;
-}
-
-// InitInput is called after InitExtensions, so we're guaranteed that
-// vncExtensionInit() has already been called.
-
-void InitInput(int argc, char *argv[])
-{
- DeviceIntPtr p, k;
- p = AddInputDevice(vfbMouseProc, TRUE);
- k = AddInputDevice(vfbKeybdProc, TRUE);
- RegisterPointerDevice(p);
- RegisterKeyboardDevice(k);
- miRegisterPointerDevice(screenInfo.screens[0], p);
- (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
-}
+++ /dev/null
-
- VNCUNIXDIR = VncUnixDir
- VNCCOMMONDIR = VncCommonDir
- VNCLIBS = VncExtLibs
- VNCINCLUDE = -I$(VNCCOMMONDIR) -I$(VNCUNIXDIR)/vncconfig
-
-#define CplusplusSource
-
-#define IHaveModules
-#include <Server.tmpl>
-
- SRCS = vncExtInit.cc vncHooks.cc xf86vncModule.cc XserverDesktop.cc
- OBJS = vncExtInit.o vncHooks.o xf86vncModule.o XserverDesktop.o
-INCLUDES = -I.. -I../../include -I$(EXTINCSRC) -I$(XINCLUDESRC) \
- -I$(FONTINCSRC) -I$(XF86COMSRC) \
- -I../../render $(VNCINCLUDE)
- DEFINES = $(STD_DEFINES) -DGC_HAS_COMPOSITE_CLIP -DXFree86LOADER
-
-LinkSourceFile(vncExtInit.cc,..)
-LinkSourceFile(vncHooks.cc,..)
-LinkSourceFile(xf86vncModule.cc,..)
-LinkSourceFile(XserverDesktop.cc,..)
-
-ModuleObjectRule()
-/*
- LibraryModuleTarget(vnc,$(OBJS) $(VNCLIBS))
- InstallLibraryModule(vnc,$(MODULEDIR),extensions)
-*/
-
-/* *** The imake rules don't define a ModuleCplusplusObjectRule so
- for now we just assume that NormalCplusplusObjectRule will
- do the job.
- NB: If we don't do this then make will assume CC is the C++ compiler!
-*/
-NormalCplusplusObjectRule()
-
-/*
- * CplusplusDynamicModuleTarget - build a module to be dynamically loaded
- */
-#ifndef CplusplusDynamicModuleTarget
-#define CplusplusDynamicModuleTarget(module,modlist) @@\
-AllTarget(module) @@\
- @@\
-module: modlist @@\
- RemoveFile($@) @@\
- $(CXX) -o $@ $(SHLIBLDFLAGS) modlist @@\
- @@\
-clean:: @@\
- RemoveFile(module)
-#endif /* CplusplusDynamicModuleTarget */
-
-
-
-CplusplusDynamicModuleTarget(vnc.so,$(OBJS) $(VNCLIBS))
-InstallDynamicModule(vnc.so,$(MODULEDIR),extensions)
-
-DependTarget()
-
-/*
- InstallDriverSDKLibraryModule(vnc,$(DRIVERSDKMODULEDIR),extensions)
-*/
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-
-#include <stdio.h>
-
-extern "C" {
-#define class c_class
-#define NEED_EVENTS
-#include "X.h"
-#include "Xproto.h"
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "extnsionst.h"
-#include "scrnintstr.h"
-#include "selection.h"
-#define _VNCEXT_SERVER_
-#define _VNCEXT_PROTO_
-#include "vncExt.h"
-#undef class
-#undef xalloc
-}
-
-#include <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-#include <rfb/util.h>
-#include <rfb/ServerCore.h>
-#include <rfb/SSecurityFactoryStandard.h>
-#include <rdr/HexOutStream.h>
-#include <rfb/LogWriter.h>
-#undef max
-#undef min
-#include <network/TcpSocket.h>
-
-#include "XserverDesktop.h"
-#include "vncHooks.h"
-#include "vncExtInit.h"
-
-extern "C" {
-
- extern void vncExtensionInit();
- static void vncResetProc(ExtensionEntry* extEntry);
- static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask);
- static void vncWakeupHandler(pointer data, int nfds, pointer readmask);
- static void vncClientStateChange(CallbackListPtr*, pointer, pointer);
- static void SendSelectionChangeEvent(Atom selection);
- static int ProcVncExtDispatch(ClientPtr client);
- static int SProcVncExtDispatch(ClientPtr client);
-
- extern char *display;
-
- extern Selection *CurrentSelections;
- extern int NumCurrentSelections;
-}
-
-using namespace rfb;
-
-static rfb::LogWriter vlog("vncext");
-
-static unsigned long vncExtGeneration = 0;
-static bool initialised = false;
-static XserverDesktop* desktop[MAXSCREENS] = { 0, };
-void* vncFbptr[MAXSCREENS] = { 0, };
-
-static char* clientCutText = 0;
-static int clientCutTextLen = 0;
-
-static XserverDesktop* queryConnectDesktop = 0;
-static void* queryConnectId = 0;
-static int queryConnectTimeout = 0;
-static OsTimerPtr queryConnectTimer = 0;
-
-static struct VncInputSelect* vncInputSelectHead = 0;
-struct VncInputSelect {
- VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m)
- {
- next = vncInputSelectHead;
- vncInputSelectHead = this;
- }
- ClientPtr client;
- Window window;
- int mask;
- VncInputSelect* next;
-};
-
-static int nPrevSelections = 0;
-static TimeStamp* prevSelectionTimes = 0;
-
-static int vncErrorBase = 0;
-static int vncEventBase = 0;
-static char* vncPasswdFile = 0;
-int vncInetdSock = -1;
-
-rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
- &SSecurityFactoryStandard::vncAuthPasswdFile);
-rfb::StringParameter httpDir("httpd",
- "Directory containing files to serve via HTTP",
- "");
-rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
-rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
- &rfb::Server::clientWaitTimeMillis);
-rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
-rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
-rfb::BoolParameter localhostOnly("localhost",
- "Only allow connections from localhost",
- false);
-
-void vncExtensionInit()
-{
- if (vncExtGeneration == serverGeneration) {
- vlog.error("vncExtensionInit: called twice in same generation?");
- return;
- }
- vncExtGeneration = serverGeneration;
-
- ExtensionEntry* extEntry
- = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,
- ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,
- StandardMinorOpcode);
- if (!extEntry) {
- ErrorF("vncExtInit: AddExtension failed\n");
- return;
- }
-
- vncErrorBase = extEntry->errorBase;
- vncEventBase = extEntry->eventBase;
-
- vlog.info("VNC extension running!");
-
- if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
- FatalError("AddCallback failed\n");
- }
-
- try {
- if (!initialised) {
- rfb::initStdIOLoggers();
- initialised = true;
- }
-
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
-
- if (!desktop[scr]) {
- network::TcpListener* listener = 0;
- network::TcpListener* httpListener = 0;
- if (scr == 0 && vncInetdSock != -1) {
- if (network::TcpSocket::isSocket(vncInetdSock) &&
- !network::TcpSocket::isConnected(vncInetdSock))
- {
- listener = new network::TcpListener(0, 0, vncInetdSock, true);
- vlog.info("inetd wait");
- }
- } else {
- int port = rfbport;
- if (port == 0) port = 5900 + atoi(display);
- port += 1000 * scr;
- listener = new network::TcpListener(port, localhostOnly);
- vlog.info("Listening for VNC connections on port %d",port);
- CharArray httpDirStr(httpDir.getData());
- if (httpDirStr.buf[0]) {
- port = httpPort;
- if (port == 0) port = 5800 + atoi(display);
- port += 1000 * scr;
- httpListener = new network::TcpListener(port, localhostOnly);
- vlog.info("Listening for HTTP connections on port %d",port);
- }
- }
-
- CharArray desktopNameStr(desktopName.getData());
- desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener,
- httpListener,
- desktopNameStr.buf,
- vncFbptr[scr]);
- vlog.info("created VNC server for screen %d", scr);
-
- if (scr == 0 && vncInetdSock != -1 && !listener) {
- network::Socket* sock = new network::TcpSocket(vncInetdSock);
- desktop[scr]->addClient(sock, false);
- vlog.info("added inetd sock");
- }
-
- } else {
- desktop[scr]->serverReset(screenInfo.screens[scr]);
- }
-
- vncHooksInit(screenInfo.screens[scr], desktop[scr]);
- }
-
- RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0);
-
- } catch (rdr::Exception& e) {
- vlog.error("vncExtInit: %s",e.str());
- }
-}
-
-static void vncResetProc(ExtensionEntry* extEntry)
-{
-}
-
-//
-// vncBlockHandler - called just before the X server goes into select(). Call
-// on to the block handler for each desktop. Then check whether any of the
-// selections have changed, and if so, notify any interested X clients.
-//
-
-static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask)
-{
- fd_set* fds = (fd_set*)readmask;
-
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- if (desktop[scr]) {
- desktop[scr]->blockHandler(fds);
- }
- }
-
- if (nPrevSelections != NumCurrentSelections) {
- prevSelectionTimes
- = (TimeStamp*)xnfrealloc(prevSelectionTimes,
- NumCurrentSelections * sizeof(TimeStamp));
- for (int i = nPrevSelections; i < NumCurrentSelections; i++) {
- prevSelectionTimes[i].months = 0;
- prevSelectionTimes[i].milliseconds = 0;
- }
- nPrevSelections = NumCurrentSelections;
- }
- for (int i = 0; i < NumCurrentSelections; i++) {
- if (CurrentSelections[i].lastTimeChanged.months
- != prevSelectionTimes[i].months ||
- CurrentSelections[i].lastTimeChanged.milliseconds
- != prevSelectionTimes[i].milliseconds)
- {
- SendSelectionChangeEvent(CurrentSelections[i].selection);
- prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged;
- }
- }
-}
-
-static void vncWakeupHandler(pointer data, int nfds, pointer readmask)
-{
- fd_set* fds = (fd_set*)readmask;
-
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- if (desktop[scr]) {
- desktop[scr]->wakeupHandler(fds, nfds);
- }
- }
-}
-
-static void vncClientStateChange(CallbackListPtr*, pointer, pointer p)
-{
- ClientPtr client = ((NewClientInfoRec*)p)->client;
- if (client->clientState == ClientStateGone) {
- VncInputSelect** nextPtr = &vncInputSelectHead;
- for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {
- if (cur->client == client) {
- *nextPtr = cur->next;
- delete cur;
- continue;
- }
- nextPtr = &cur->next;
- }
- }
-}
-
-void vncBell()
-{
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- if (desktop[scr]) {
- desktop[scr]->bell();
- }
- }
-}
-
-void vncClientGone(int fd)
-{
- if (fd == vncInetdSock) {
- fprintf(stderr,"inetdSock client gone\n");
- GiveUp(0);
- }
-}
-
-void vncClientCutText(const char* str, int len)
-{
- delete [] clientCutText;
- clientCutText = new char[len];
- memcpy(clientCutText, str, len);
- clientCutTextLen = len;
- xVncExtClientCutTextNotifyEvent ev;
- ev.type = vncEventBase + VncExtClientCutTextNotify;
- for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
- if (cur->mask & VncExtClientCutTextMask) {
- ev.sequenceNumber = cur->client->sequence;
- ev.window = cur->window;
- ev.time = GetTimeInMillis();
- if (cur->client->swapped) {
- int n;
- swaps(&ev.sequenceNumber, n);
- swapl(&ev.window, n);
- swapl(&ev.time, n);
- }
- WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent),
- (char *)&ev);
- }
- }
-}
-
-
-static CARD32 queryConnectTimerCallback(OsTimerPtr timer,
- CARD32 now, pointer arg)
-{
- if (queryConnectTimeout)
- queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed");
- // Re-notify clients, causing them to discover that we're done
- vncQueryConnect(queryConnectDesktop, queryConnectId);
- return 0;
-}
-
-void vncQueryConnect(XserverDesktop* desktop, void* opaqueId)
-{
- // Only one query can be processed at any one time
- if (queryConnectTimeout && ((desktop != queryConnectDesktop) ||
- (opaqueId != queryConnectId))) {
- desktop->approveConnection(opaqueId, false,
- "Another connection is currently being queried.");
- return;
- }
-
- // Get the query timeout. If it's zero, there is no query.
- queryConnectTimeout = desktop->getQueryTimeout(opaqueId);
- queryConnectId = queryConnectTimeout ? opaqueId : 0;
- queryConnectDesktop = queryConnectTimeout ? desktop : 0;
-
- // Notify clients
- bool notified = false;
- xVncExtQueryConnectNotifyEvent ev;
- ev.type = vncEventBase + VncExtQueryConnectNotify;
- for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
- if (cur->mask & VncExtQueryConnectMask) {
- ev.sequenceNumber = cur->client->sequence;
- ev.window = cur->window;
- if (cur->client->swapped) {
- int n;
- swaps(&ev.sequenceNumber, n);
- swapl(&ev.window, n);
- }
- WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),
- (char *)&ev);
- notified = true;
- }
- }
-
- // If we're being asked to query a connection (rather than to cancel
- // a query), and haven't been able to notify clients then reject it.
- if (queryConnectTimeout && !notified) {
- queryConnectTimeout = 0;
- queryConnectId = 0;
- queryConnectDesktop = 0;
- desktop->approveConnection(opaqueId, false,
- "Unable to query the local user to accept the connection.");
- return;
- }
-
- // Set a timer so that if no-one ever responds, we will eventually
- // reject the connection
- // NB: We don't set a timer if sock is null, since that indicates
- // that pending queries should be cancelled.
- if (queryConnectDesktop)
- queryConnectTimer = TimerSet(queryConnectTimer, 0,
- queryConnectTimeout*2000,
- queryConnectTimerCallback, 0);
- else
- TimerCancel(queryConnectTimer);
-}
-
-static void SendSelectionChangeEvent(Atom selection)
-{
- xVncExtSelectionChangeNotifyEvent ev;
- ev.type = vncEventBase + VncExtSelectionChangeNotify;
- for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
- if (cur->mask & VncExtSelectionChangeMask) {
- ev.sequenceNumber = cur->client->sequence;
- ev.window = cur->window;
- ev.selection = selection;
- if (cur->client->swapped) {
- int n;
- swaps(&ev.sequenceNumber, n);
- swapl(&ev.window, n);
- swapl(&ev.selection, n);
- }
- WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent),
- (char *)&ev);
- }
- }
-}
-
-static int ProcVncExtSetParam(ClientPtr client)
-{
- REQUEST(xVncExtSetParamReq);
- REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen);
- CharArray param(stuff->paramLen+1);
- strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
- param.buf[stuff->paramLen] = 0;
-
- xVncExtSetParamReply rep;
- int n;
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.success = rfb::Configuration::setParam(param.buf);
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
- WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);
- return (client->noClientException);
-}
-
-static int SProcVncExtSetParam(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtSetParamReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);
- return ProcVncExtSetParam(client);
-}
-
-static int ProcVncExtGetParam(ClientPtr client)
-{
- REQUEST(xVncExtGetParamReq);
- REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);
- CharArray param(stuff->paramLen+1);
- strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
- param.buf[stuff->paramLen] = 0;
-
- xVncExtGetParamReply rep;
- int n;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.success = 0;
- int len = 0;
- char* value = 0;
- rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
- // Hack to avoid exposing password!
- if (strcasecmp(param.buf, "Password") == 0)
- p = 0;
- if (p) {
- value = p->getValueStr();
- rep.success = 1;
- len = value ? strlen(value) : 0;
- }
- rep.length = (len + 3) >> 2;
- rep.valueLen = len;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.valueLen, n);
- }
- WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);
- if (value)
- WriteToClient(client, len, value);
- delete [] value;
- return (client->noClientException);
-}
-
-static int SProcVncExtGetParam(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtGetParamReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);
- return ProcVncExtGetParam(client);
-}
-
-static int ProcVncExtGetParamDesc(ClientPtr client)
-{
- REQUEST(xVncExtGetParamDescReq);
- REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);
- CharArray param(stuff->paramLen+1);
- strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
- param.buf[stuff->paramLen] = 0;
-
- xVncExtGetParamDescReply rep;
- int n;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.success = 0;
- int len = 0;
- const char* desc = 0;
- rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
- if (p) {
- desc = p->getDescription();
- rep.success = 1;
- len = desc ? strlen(desc) : 0;
- }
- rep.length = (len + 3) >> 2;
- rep.descLen = len;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.descLen, n);
- }
- WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);
- if (desc)
- WriteToClient(client, len, (char*)desc);
- return (client->noClientException);
-}
-
-static int SProcVncExtGetParamDesc(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtGetParamDescReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);
- return ProcVncExtGetParamDesc(client);
-}
-
-static int ProcVncExtListParams(ClientPtr client)
-{
- REQUEST(xVncExtListParamsReq);
- REQUEST_SIZE_MATCH(xVncExtListParamsReq);
-
- xVncExtListParamsReply rep;
- int n;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
-
- int nParams = 0;
- int len = 0;
- for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
- int l = strlen(i.param->getName());
- if (l <= 255) {
- nParams++;
- len += l + 1;
- }
- }
- rep.length = (len + 3) >> 2;
- rep.nParams = nParams;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swaps(&rep.nParams, n);
- }
- WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);
- rdr::U8* data = new rdr::U8[len];
- rdr::U8* ptr = data;
- for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
- int l = strlen(i.param->getName());
- if (l <= 255) {
- *ptr++ = l;
- memcpy(ptr, i.param->getName(), l);
- ptr += l;
- }
- }
- WriteToClient(client, len, (char*)data);
- delete [] data;
- return (client->noClientException);
-}
-
-static int SProcVncExtListParams(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtListParamsReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xVncExtListParamsReq);
- return ProcVncExtListParams(client);
-}
-
-static int ProcVncExtSetServerCutText(ClientPtr client)
-{
- REQUEST(xVncExtSetServerCutTextReq);
- REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen);
- char* str = new char[stuff->textLen+1];
- strncpy(str, (char*)&stuff[1], stuff->textLen);
- str[stuff->textLen] = 0;
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- if (desktop[scr]) {
- desktop[scr]->serverCutText(str, stuff->textLen);
- }
- }
- delete [] str;
- return (client->noClientException);
-}
-
-static int SProcVncExtSetServerCutText(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtSetServerCutTextReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq);
- swapl(&stuff->textLen, n);
- return ProcVncExtSetServerCutText(client);
-}
-
-static int ProcVncExtGetClientCutText(ClientPtr client)
-{
- REQUEST(xVncExtGetClientCutTextReq);
- REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
-
- xVncExtGetClientCutTextReply rep;
- int n;
- rep.type = X_Reply;
- rep.length = (clientCutTextLen + 3) >> 2;
- rep.sequenceNumber = client->sequence;
- rep.textLen = clientCutTextLen;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.textLen, n);
- }
- WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep);
- if (clientCutText)
- WriteToClient(client, clientCutTextLen, clientCutText);
- return (client->noClientException);
-}
-
-static int SProcVncExtGetClientCutText(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtGetClientCutTextReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
- return ProcVncExtGetClientCutText(client);
-}
-
-static int ProcVncExtSelectInput(ClientPtr client)
-{
- REQUEST(xVncExtSelectInputReq);
- REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
- VncInputSelect** nextPtr = &vncInputSelectHead;
- VncInputSelect* cur;
- for (cur = vncInputSelectHead; cur; cur = *nextPtr) {
- if (cur->client == client && cur->window == stuff->window) {
- cur->mask = stuff->mask;
- if (!cur->mask) {
- *nextPtr = cur->next;
- delete cur;
- }
- break;
- }
- nextPtr = &cur->next;
- }
- if (!cur) {
- cur = new VncInputSelect(client, stuff->window, stuff->mask);
- }
- return (client->noClientException);
-}
-
-static int SProcVncExtSelectInput(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtSelectInputReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
- swapl(&stuff->window, n);
- swapl(&stuff->mask, n);
- return ProcVncExtSelectInput(client);
-}
-
-static int ProcVncExtConnect(ClientPtr client)
-{
- REQUEST(xVncExtConnectReq);
- REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);
- CharArray str(stuff->strLen+1);
- strncpy(str.buf, (char*)&stuff[1], stuff->strLen);
- str.buf[stuff->strLen] = 0;
-
- xVncExtConnectReply rep;
- rep.success = 0;
- if (desktop[0]) {
- if (stuff->strLen == 0) {
- try {
- desktop[0]->disconnectClients();
- rep.success = 1;
- } catch (rdr::Exception& e) {
- vlog.error("Disconnecting all clients: %s",e.str());
- }
- } else {
- int port = 5500;
- for (int i = 0; i < stuff->strLen; i++) {
- if (str.buf[i] == ':') {
- port = atoi(&str.buf[i+1]);
- str.buf[i] = 0;
- break;
- }
- }
-
- try {
- network::Socket* sock = new network::TcpSocket(str.buf, port);
- desktop[0]->addClient(sock, true);
- rep.success = 1;
- } catch (rdr::Exception& e) {
- vlog.error("Reverse connection: %s",e.str());
- }
- }
- }
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (client->swapped) {
- int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
- WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);
- return (client->noClientException);
-}
-
-static int SProcVncExtConnect(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtConnectReq);
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);
- return ProcVncExtConnect(client);
-}
-
-
-static int ProcVncExtGetQueryConnect(ClientPtr client)
-{
- REQUEST(xVncExtGetQueryConnectReq);
- REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
-
- const char *qcAddress=0, *qcUsername=0;
- int qcTimeout;
- if (queryConnectDesktop)
- qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId,
- &qcAddress, &qcUsername);
- else
- qcTimeout = 0;
-
- xVncExtGetQueryConnectReply rep;
- int n;
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.timeout = qcTimeout;
- rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;
- rep.userLen = qcTimeout ? strlen(qcUsername) : 0;
- rep.opaqueId = (CARD32)queryConnectId;
- rep.length = (rep.userLen + rep.addrLen + 3) >> 2;
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.userLen, n);
- swapl(&rep.addrLen, n);
- swapl(&rep.timeout, n);
- swapl(&rep.opaqueId, n);
- }
- WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);
- if (qcTimeout)
- WriteToClient(client, strlen(qcAddress), (char*)qcAddress);
- if (qcTimeout)
- WriteToClient(client, strlen(qcUsername), (char*)qcUsername);
- return (client->noClientException);
-}
-
-static int SProcVncExtGetQueryConnect(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtGetQueryConnectReq);
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
- return ProcVncExtGetQueryConnect(client);
-}
-
-
-static int ProcVncExtApproveConnect(ClientPtr client)
-{
- REQUEST(xVncExtApproveConnectReq);
- REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
- if (queryConnectId == (void*)stuff->opaqueId) {
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- if (desktop[scr]) {
- desktop[scr]->approveConnection(queryConnectId, stuff->approve,
- "Connection rejected by local user");
- }
- }
- // Inform other clients of the event and tidy up
- vncQueryConnect(queryConnectDesktop, queryConnectId);
- }
- return (client->noClientException);
-}
-
-static int SProcVncExtApproveConnect(ClientPtr client)
-{
- register char n;
- REQUEST(xVncExtApproveConnectReq);
- swaps(&stuff->length, n);
- swapl(&stuff->opaqueId, n);
- REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
- return ProcVncExtApproveConnect(client);
-}
-
-
-static int ProcVncExtDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- switch (stuff->data) {
- case X_VncExtSetParam:
- return ProcVncExtSetParam(client);
- case X_VncExtGetParam:
- return ProcVncExtGetParam(client);
- case X_VncExtGetParamDesc:
- return ProcVncExtGetParamDesc(client);
- case X_VncExtListParams:
- return ProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return ProcVncExtSetServerCutText(client);
- case X_VncExtGetClientCutText:
- return ProcVncExtGetClientCutText(client);
- case X_VncExtSelectInput:
- return ProcVncExtSelectInput(client);
- case X_VncExtConnect:
- return ProcVncExtConnect(client);
- case X_VncExtGetQueryConnect:
- return ProcVncExtGetQueryConnect(client);
- case X_VncExtApproveConnect:
- return ProcVncExtApproveConnect(client);
- default:
- return BadRequest;
- }
-}
-
-static int SProcVncExtDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- switch (stuff->data) {
- case X_VncExtSetParam:
- return SProcVncExtSetParam(client);
- case X_VncExtGetParam:
- return SProcVncExtGetParam(client);
- case X_VncExtGetParamDesc:
- return SProcVncExtGetParamDesc(client);
- case X_VncExtListParams:
- return SProcVncExtListParams(client);
- case X_VncExtSetServerCutText:
- return SProcVncExtSetServerCutText(client);
- case X_VncExtGetClientCutText:
- return SProcVncExtGetClientCutText(client);
- case X_VncExtSelectInput:
- return SProcVncExtSelectInput(client);
- case X_VncExtConnect:
- return SProcVncExtConnect(client);
- case X_VncExtGetQueryConnect:
- return SProcVncExtGetQueryConnect(client);
- case X_VncExtApproveConnect:
- return SProcVncExtApproveConnect(client);
- default:
- return BadRequest;
- }
-}
-
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __VNCEXTINIT_H__
-#define __VNCEXTINIT_H__
-
-#include <rfb/Configuration.h>
-#include "XserverDesktop.h"
-
-extern void vncClientCutText(const char* str, int len);
-extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId);
-extern void vncClientGone(int fd);
-extern void vncBell();
-extern void* vncFbptr[];
-extern int vncInetdSock;
-extern rfb::StringParameter httpDir;
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-
-#include <stdio.h>
-#include "XserverDesktop.h"
-#include "vncHooks.h"
-
-extern "C" {
-#define class c_class
-#define private c_private
-#include "scrnintstr.h"
-#include "windowstr.h"
-#include "gcstruct.h"
-#include "regionstr.h"
-#include "dixfontstr.h"
-#include "colormapst.h"
-#ifdef RENDER
-#include "picturestr.h"
-#endif
-
-#ifdef GC_HAS_COMPOSITE_CLIP
-#define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip)
-#else
-#include "mfb.h"
-#define COMPOSITE_CLIP(gc) \
- (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
-#endif
-
-#undef class
-#undef private
-}
-
-#include "RegionHelper.h"
-
-#define DBGPRINT(x) //(fprintf x)
-
-// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
-// operations like Polylines and PolySegment. If the operation is more complex
-// than this, we simply use the bounding box. Ideally it would be a
-// command-line option, but that would involve an extra malloc each time, so we
-// fix it here.
-#define MAX_RECTS_PER_OP 5
-
-static unsigned long vncHooksGeneration = 0;
-
-// vncHooksScreenRec and vncHooksGCRec contain pointers to the original
-// functions which we "wrap" in order to hook the screen changes. The screen
-// functions are each wrapped individually, while the GC "funcs" and "ops" are
-// wrapped as a unit.
-
-typedef struct {
- XserverDesktop* desktop;
-
- CloseScreenProcPtr CloseScreen;
- CreateGCProcPtr CreateGC;
- PaintWindowBackgroundProcPtr PaintWindowBackground;
- PaintWindowBorderProcPtr PaintWindowBorder;
- CopyWindowProcPtr CopyWindow;
- ClearToBackgroundProcPtr ClearToBackground;
- RestoreAreasProcPtr RestoreAreas;
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
- DisplayCursorProcPtr DisplayCursor;
- ScreenBlockHandlerProcPtr BlockHandler;
-#ifdef RENDER
- CompositeProcPtr Composite;
-#endif
-} vncHooksScreenRec, *vncHooksScreenPtr;
-
-typedef struct {
- GCFuncs *wrappedFuncs;
- GCOps *wrappedOps;
-} vncHooksGCRec, *vncHooksGCPtr;
-
-static int vncHooksScreenIndex;
-static int vncHooksGCIndex;
-
-
-// screen functions
-
-static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
-static Bool vncHooksCreateGC(GCPtr pGC);
-static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
- int what);
-static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
- int what);
-static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion);
-static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
- int h, Bool generateExposures);
-static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
-static void vncHooksInstallColormap(ColormapPtr pColormap);
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef);
-static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor);
-static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask);
-#ifdef RENDER
-static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
- PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
- INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
-#endif
-
-// GC "funcs"
-
-static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable);
-static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
-static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
-static void vncHooksDestroyGC(GCPtr pGC);
-static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects);
-static void vncHooksDestroyClip(GCPtr pGC);
-static void vncHooksCopyClip(GCPtr dst, GCPtr src);
-
-static GCFuncs vncHooksGCFuncs = {
- vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
- vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
-};
-
-// GC "ops"
-
-static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted);
-static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted);
-static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits);
-static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty);
-static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane);
-static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts);
-static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts);
-static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs);
-static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
-static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
-static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts);
-static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects);
-static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs);
-static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
-static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
-static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars);
-static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars);
-static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
-static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
-static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y);
-
-static GCOps vncHooksGCOps = {
- vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
- vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
- vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
- vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
- vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
- vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
-};
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-// vncHooksInit() is called at initialisation time and every time the server
-// resets. It is called once for each screen, but the indexes are only
-// allocated once for each server generation.
-
-Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
-{
- vncHooksScreenPtr vncHooksScreen;
-
- if (vncHooksGeneration != serverGeneration) {
- vncHooksGeneration = serverGeneration;
-
- vncHooksScreenIndex = AllocateScreenPrivateIndex();
- if (vncHooksScreenIndex < 0) {
- ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n");
- return FALSE;
- }
-
- vncHooksGCIndex = AllocateGCPrivateIndex();
- if (vncHooksGCIndex < 0) {
- ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n");
- return FALSE;
- }
- }
-
- if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) {
- ErrorF("vncHooksInit: AllocateGCPrivate failed\n");
- return FALSE;
- }
-
- vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec));
- pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen;
-
- vncHooksScreen->desktop = desktop;
-
- vncHooksScreen->CloseScreen = pScreen->CloseScreen;
- vncHooksScreen->CreateGC = pScreen->CreateGC;
- vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground;
- vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder;
- vncHooksScreen->CopyWindow = pScreen->CopyWindow;
- vncHooksScreen->ClearToBackground = pScreen->ClearToBackground;
- vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
- vncHooksScreen->InstallColormap = pScreen->InstallColormap;
- vncHooksScreen->StoreColors = pScreen->StoreColors;
- vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
- vncHooksScreen->BlockHandler = pScreen->BlockHandler;
-#ifdef RENDER
- PictureScreenPtr ps;
- ps = GetPictureScreenIfSet(pScreen);
- if (ps) {
- vncHooksScreen->Composite = ps->Composite;
- }
-#endif
-
- pScreen->CloseScreen = vncHooksCloseScreen;
- pScreen->CreateGC = vncHooksCreateGC;
- pScreen->PaintWindowBackground = vncHooksPaintWindowBackground;
- pScreen->PaintWindowBorder = vncHooksPaintWindowBorder;
- pScreen->CopyWindow = vncHooksCopyWindow;
- pScreen->ClearToBackground = vncHooksClearToBackground;
- pScreen->RestoreAreas = vncHooksRestoreAreas;
- pScreen->InstallColormap = vncHooksInstallColormap;
- pScreen->StoreColors = vncHooksStoreColors;
- pScreen->DisplayCursor = vncHooksDisplayCursor;
- pScreen->BlockHandler = vncHooksBlockHandler;
-#ifdef RENDER
- if (ps) {
- ps->Composite = vncHooksComposite;
- }
-#endif
-
- return TRUE;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// screen functions
-//
-
-// SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function.
-// It would be nice to do this with a C++ class, but each function is of a
-// distinct type, so it would have to use templates, and it's not worth that
-// much pain.
-
-#define SCREEN_UNWRAP(scrn,field) \
- ScreenPtr pScreen = scrn; \
- vncHooksScreenPtr vncHooksScreen \
- = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
- pScreen->field = vncHooksScreen->field; \
- DBGPRINT((stderr,"vncHooks" #field " called\n"));
-
-#define SCREEN_REWRAP(field) pScreen->field = vncHooks##field;
-
-
-// CloseScreen - unwrap the screen functions and call the original CloseScreen
-// function
-
-static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
-{
- SCREEN_UNWRAP(pScreen_, CloseScreen);
-
- pScreen->CreateGC = vncHooksScreen->CreateGC;
- pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground;
- pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder;
- pScreen->CopyWindow = vncHooksScreen->CopyWindow;
- pScreen->ClearToBackground = vncHooksScreen->ClearToBackground;
- pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
- pScreen->InstallColormap = vncHooksScreen->InstallColormap;
- pScreen->StoreColors = vncHooksScreen->StoreColors;
- pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
- pScreen->BlockHandler = vncHooksScreen->BlockHandler;
-
- xfree((pointer)vncHooksScreen);
-
- DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
-
- return (*pScreen->CloseScreen)(i, pScreen);
-}
-
-// CreateGC - wrap the "GC funcs"
-
-static Bool vncHooksCreateGC(GCPtr pGC)
-{
- SCREEN_UNWRAP(pGC->pScreen, CreateGC);
-
- vncHooksGCPtr vncHooksGC
- = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
-
- Bool ret = (*pScreen->CreateGC) (pGC);
-
- vncHooksGC->wrappedOps = 0;
- vncHooksGC->wrappedFuncs = pGC->funcs;
- pGC->funcs = &vncHooksGCFuncs;
-
- SCREEN_REWRAP(CreateGC);
-
- return ret;
-}
-
-// PaintWindowBackground - changed region is the given region
-
-static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
- int what)
-{
- SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground);
-
- RegionHelper changed(pScreen, pRegion);
-
- (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(PaintWindowBackground);
-}
-
-// PaintWindowBorder - changed region is the given region
-
-static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
- int what)
-{
- SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
-
- RegionHelper changed(pScreen, pRegion);
-
- (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(PaintWindowBorder);
-}
-
-// CopyWindow - destination of the copy is the old region, clipped by
-// borderClip, translated by the delta. This call only does the copy - it
-// doesn't affect any other bits.
-
-static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr pOldRegion)
-{
- SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow);
-
- RegionHelper copied(pScreen, pOldRegion);
- int dx = pWin->drawable.x - ptOldOrg.x;
- int dy = pWin->drawable.y - ptOldOrg.y;
- REGION_TRANSLATE(pScreen, copied.reg, dx, dy);
- REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg,
- &pWin->borderClip);
-
- (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
-
- vncHooksScreen->desktop->add_copied(copied.reg, dx, dy);
-
- SCREEN_REWRAP(CopyWindow);
-}
-
-// ClearToBackground - changed region is the given rectangle, clipped by
-// clipList, but only if generateExposures is false.
-
-static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
- int h, Bool generateExposures)
-{
- SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground);
-
- BoxRec box;
- 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);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList);
-
- (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
-
- if (!generateExposures) {
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- SCREEN_REWRAP(ClearToBackground);
-}
-
-// RestoreAreas - changed region is the given region
-
-static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
-{
- SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas);
-
- RegionHelper changed(pScreen, pRegion);
-
- RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- SCREEN_REWRAP(RestoreAreas);
-
- return result;
-}
-
-// InstallColormap - get the new colormap
-
-static void vncHooksInstallColormap(ColormapPtr pColormap)
-{
- SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
-
- (*pScreen->InstallColormap) (pColormap);
-
- vncHooksScreen->desktop->setColormap(pColormap);
-
- SCREEN_REWRAP(InstallColormap);
-}
-
-// StoreColors - get the colormap changes
-
-static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
- xColorItem* pdef)
-{
- SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
-
- (*pScreen->StoreColors) (pColormap, ndef, pdef);
-
- vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
-
- SCREEN_REWRAP(StoreColors);
-}
-
-// DisplayCursor - get the cursor shape
-
-static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor)
-{
- SCREEN_UNWRAP(pScreen_, DisplayCursor);
-
- Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor);
-
- vncHooksScreen->desktop->setCursor(cursor);
-
- SCREEN_REWRAP(DisplayCursor);
-
- return ret;
-}
-
-// BlockHandler - ignore any changes during the block handler - it's likely
-// these are just drawing the cursor.
-
-static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
- pointer pReadmask)
-{
- SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler);
-
- vncHooksScreen->desktop->ignoreHooks(true);
-
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- vncHooksScreen->desktop->ignoreHooks(false);
-
- SCREEN_REWRAP(BlockHandler);
-}
-
-// Composite - needed for RENDER
-
-#ifdef RENDER
-void vncHooksComposite(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;
- vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr);
- BoxRec box;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- rfb::Rect rect1, rect2;
-
- rect1.setXYWH(pDst->pDrawable->x + xDst,
- pDst->pDrawable->y + yDst,
- width,
- height);
-
- rect2 = rect1.intersect(vncHooksScreen->desktop->getRect());
- if (!rect2.is_empty()) {
- box.x1 = rect2.tl.x;
- box.y1 = rect2.tl.y;
- box.x2 = rect2.br.x;
- box.y2 = rect2.br.y;
- RegionHelper changed(pScreen, &box, 0);
- vncHooksScreen->desktop->add_changed(changed.reg);
- }
-
- ps->Composite = vncHooksScreen->Composite;
- (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
- xMask, yMask, xDst, yDst, width, height);
- ps->Composite = vncHooksComposite;
-}
-
-#endif /* RENDER */
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// GC "funcs"
-//
-
-// GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its
-// constructor and rewraps them in its destructor.
-
-class GCFuncUnwrapper {
-public:
- GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) {
- vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
- pGC->funcs = vncHooksGC->wrappedFuncs;
- if (vncHooksGC->wrappedOps)
- pGC->ops = vncHooksGC->wrappedOps;
- }
- ~GCFuncUnwrapper() {
- vncHooksGC->wrappedFuncs = pGC->funcs;
- pGC->funcs = &vncHooksGCFuncs;
- if (vncHooksGC->wrappedOps) {
- vncHooksGC->wrappedOps = pGC->ops;
- pGC->ops = &vncHooksGCOps;
- }
- }
- GCPtr pGC;
- vncHooksGCPtr vncHooksGC;
-};
-
-
-// ValidateGC - wrap the "ops" if a viewable window
-
-static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable)
-{
- GCFuncUnwrapper u(pGC);
-
- DBGPRINT((stderr,"vncHooksValidateGC called\n"));
-
- (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
-
- u.vncHooksGC->wrappedOps = 0;
- 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)) {
- u.vncHooksGC->wrappedOps = pGC->ops;
- DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
- }
- }
-}
-
-// Other GC funcs - just unwrap and call on
-
-static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->ChangeGC) (pGC, mask);
-}
-static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
- GCFuncUnwrapper u(dst);
- (*dst->funcs->CopyGC) (src, mask, dst);
-}
-static void vncHooksDestroyGC(GCPtr pGC) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->DestroyGC) (pGC);
-}
-static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
-{
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
-}
-static void vncHooksDestroyClip(GCPtr pGC) {
- GCFuncUnwrapper u(pGC);
- (*pGC->funcs->DestroyClip) (pGC);
-}
-static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
- GCFuncUnwrapper u(dst);
- (*dst->funcs->CopyClip) (dst, src);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// GC "ops"
-//
-
-// GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its
-// constructor and rewraps them in its destructor.
-
-class GCOpUnwrapper {
-public:
- GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_)
- : pGC(pGC_), pScreen(pDrawable->pScreen)
- {
- vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
- oldFuncs = pGC->funcs;
- pGC->funcs = vncHooksGC->wrappedFuncs;
- pGC->ops = vncHooksGC->wrappedOps;
- }
- ~GCOpUnwrapper() {
- vncHooksGC->wrappedOps = pGC->ops;
- pGC->funcs = oldFuncs;
- pGC->ops = &vncHooksGCOps;
- }
- GCPtr pGC;
- vncHooksGCPtr vncHooksGC;
- GCFuncs* oldFuncs;
- ScreenPtr pScreen;
-};
-
-#define GC_OP_UNWRAPPER(pDrawable, pGC, name) \
- GCOpUnwrapper u(pDrawable, pGC); \
- ScreenPtr pScreen = (pDrawable)->pScreen; \
- vncHooksScreenPtr vncHooksScreen \
- = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
- DBGPRINT((stderr,"vncHooks" #name " called\n"));
-
-
-// FillSpans - changed region is the whole of borderClip. This is pessimistic,
-// but I believe this function is rarely used so it doesn't matter.
-
-static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int fSorted)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans);
-
- RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// SetSpans - changed region is the whole of borderClip. This is pessimistic,
-// but I believe this function is rarely used so it doesn't matter.
-
-static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
- DDXPointPtr ppt, int *pwidth, int nspans,
- int fSorted)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans);
-
- RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PutImage - changed region is the given rectangle, clipped by pCompositeClip
-
-static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
- int x, int y, int w, int h, int leftPad,
- int format, char *pBits)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PutImage);
-
- BoxRec box;
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
- pBits);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// CopyArea - destination of the copy is the dest rectangle, clipped by
-// pCompositeClip. Any parts of the destination which cannot be copied from
-// the source (could be all of it) go into the changed region.
-
-static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty)
-{
- GC_OP_UNWRAPPER(pDst, pGC, CopyArea);
-
- BoxRec box;
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper dst(pScreen, &box, 0);
- REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC));
-
- RegionHelper src(pScreen);
-
- if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) {
- box.x1 = srcx + pSrc->x;
- box.y1 = srcy + pSrc->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- src.init(&box, 0);
- REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList);
- REGION_TRANSLATE(pScreen, src.reg,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
- } else {
- src.init(NullBox, 0);
- }
-
- RegionHelper changed(pScreen, NullBox, 0);
- REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg);
- REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg);
-
- RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty);
-
- if (REGION_NOTEMPTY(pScreen, dst.reg))
- vncHooksScreen->desktop->add_copied(dst.reg,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
-
- if (REGION_NOTEMPTY(pScreen, changed.reg))
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return rgn;
-}
-
-
-// CopyPlane - changed region is the destination rectangle, clipped by
-// pCompositeClip
-
-static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
- GCPtr pGC, int srcx, int srcy, int w, int h,
- int dstx, int dsty, unsigned long plane)
-{
- GC_OP_UNWRAPPER(pDst, pGC, CopyPlane);
-
- BoxRec box;
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return rgn;
-}
-
-// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
-
-static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, xPoint *pts)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint);
-
- if (npt == 0) {
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
- return;
- }
-
- int minX = pts[0].x;
- int maxX = pts[0].x;
- int minY = pts[0].y;
- int maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (int 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 (int 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;
- }
- }
-
- BoxRec box;
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// Polylines - changed region is the union of the bounding rects of each line,
-// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines,
-// just use the bounding rect of all the lines.
-
-static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
- int npt, DDXPointPtr ppts)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, Polylines);
-
- if (npt == 0) {
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
- return;
- }
-
- int nRegRects = npt - 1;
- xRectangle regRects[MAX_RECTS_PER_OP];
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
-
- if (npt == 1)
- {
- // a single point
- nRegRects = 1;
- regRects[0].x = pDrawable->x + ppts[0].x - lw;
- regRects[0].y = pDrawable->y + ppts[0].y - lw;
- regRects[0].width = 2*lw;
- regRects[0].height = 2*lw;
- }
- else
- {
- /*
- * 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
- */
-
- int extra = lw / 2;
- if (pGC->joinStyle == JoinMiter) {
- extra = 6 * lw;
- }
-
- int prevX, prevY, curX, curY;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- prevX = ppts[0].x + pDrawable->x;
- prevY = ppts[0].y + pDrawable->y;
- minX = maxX = prevX;
- minY = maxY = prevY;
-
- for (int i = 0; i < nRegRects; i++) {
- if (mode == CoordModeOrigin) {
- curX = pDrawable->x + ppts[i+1].x;
- curY = pDrawable->y + ppts[i+1].y;
- } else {
- curX = prevX + ppts[i+1].x;
- curY = prevY + ppts[i+1].y;
- }
-
- if (prevX > curX) {
- rectX1 = curX - extra;
- rectX2 = prevX + extra + 1;
- } else {
- rectX1 = prevX - extra;
- rectX2 = curX + extra + 1;
- }
-
- if (prevY > curY) {
- rectY1 = curY - extra;
- rectY2 = prevY + extra + 1;
- } else {
- rectY1 = prevY - extra;
- rectY2 = curY + extra + 1;
- }
-
- if (nRegRects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
-
- prevX = curX;
- prevY = curY;
- }
-
- if (nRegRects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolySegment - changed region is the union of the bounding rects of each
-// segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
-// segments, just use the bounding rect of all the segments.
-
-static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
- xSegment *segs)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment);
-
- if (nseg == 0) {
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = nseg;
-
- int lw = pGC->lineWidth;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = segs[0].x1;
- minY = maxY = segs[0].y1;
-
- for (int i = 0; i < nseg; i++) {
- if (segs[i].x1 > segs[i].x2) {
- rectX1 = pDrawable->x + segs[i].x2 - extra;
- rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
- } else {
- rectX1 = pDrawable->x + segs[i].x1 - extra;
- rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
- }
-
- if (segs[i].y1 > segs[i].y2) {
- rectY1 = pDrawable->y + segs[i].y2 - extra;
- rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
- } else {
- rectY1 = pDrawable->y + segs[i].y1 - extra;
- rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
- }
-
- if (nseg <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nseg > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyRectangle - changed region is the union of the bounding rects around
-// each side of the outline rectangles, clipped by pCompositeClip. If there
-// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
-// the rectangles.
-
-static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle);
-
- if (nrects == 0) {
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP*4];
- int nRegRects = nrects * 4;
-
- int lw = pGC->lineWidth;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (int i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- 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;
- } else {
- rectX1 = pDrawable->x + rects[i].x - extra;
- rectY1 = pDrawable->y + rects[i].y - extra;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyArc - changed region is the union of bounding rects around each arc,
-// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
-// arcs, just use the bounding rect of all the arcs.
-
-static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = narcs;
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (int i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-
-// FillPolygon - changed region is the bounding rect around the polygon,
-// clipped by pCompositeClip
-
-static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
- int mode, int count, DDXPointPtr pts)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon);
-
- if (count == 0) {
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
- return;
- }
-
- int minX = pts[0].x;
- int maxX = pts[0].x;
- int minY = pts[0].y;
- int maxY = pts[0].y;
-
- if (mode == CoordModePrevious) {
- int x = pts[0].x;
- int y = pts[0].y;
-
- for (int 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 (int 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;
- }
- }
-
- BoxRec box;
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyFillRect - changed region is the union of the rectangles, clipped by
-// pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just
-// use the bounding rect of all the rectangles.
-
-static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
- xRectangle *rects)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect);
-
- if (nrects == 0) {
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = nrects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (int i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- 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;
- } else {
- rectX1 = pDrawable->x + rects[i].x;
- rectY1 = pDrawable->y + rects[i].y;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyFillArc - changed region is the union of bounding rects around each arc,
-// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs,
-// just use the bounding rect of all the arcs.
-
-static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
- xArc *arcs)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc);
-
- if (narcs == 0) {
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
- return;
- }
-
- xRectangle regRects[MAX_RECTS_PER_OP];
- int nRegRects = narcs;
-
- int lw = pGC->lineWidth;
- if (lw == 0) lw = 1;
- int extra = lw / 2;
-
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (int i = 0; i < narcs; i++) {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nRegRects = 1;
- }
-
- RegionHelper changed(pScreen, nRegRects, regRects);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// GetTextBoundingRect - calculate a bounding rectangle around n chars of a
-// font. Not particularly accurate, but good enough.
-
-static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
- int y, int nchars, BoxPtr box)
-{
- int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
- int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
- int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing),
- FONTMAXBOUNDS(font,characterWidth));
-
- box->x1 = pDrawable->x + x;
- box->y1 = pDrawable->y + y - ascent;
- box->x2 = box->x1 + charWidth * nchars;
- box->y2 = box->y1 + ascent + descent;
-
- if (FONTMINBOUNDS(font,leftSideBearing) < 0)
- box->x1 += FONTMINBOUNDS(font,leftSideBearing);
-}
-
-// PolyText8 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8);
-
- if (count == 0)
- return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return ret;
-}
-
-// PolyText16 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16);
-
- if (count == 0)
- return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-
- return ret;
-}
-
-// ImageText8 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, char *chars)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8);
-
- if (count == 0) {
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// ImageText16 - changed region is bounding rect around count chars, clipped by
-// pCompositeClip
-
-static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
- int count, unsigned short *chars)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16);
-
- if (count == 0) {
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
-// by pCompositeClip
-
-static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
-// by pCompositeClip
-
-static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
- int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt);
-
- if (nglyph == 0) {
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
- return;
- }
-
- BoxRec box;
- GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
-
-// PushPixels - changed region is the given rectangle, clipped by
-// pCompositeClip
-
-static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
- DrawablePtr pDrawable, int w, int h, int x,
- int y)
-{
- GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels);
-
- BoxRec box;
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- RegionHelper changed(pScreen, &box, 0);
-
- REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
-
- (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
-
- vncHooksScreen->desktop->add_changed(changed.reg);
-}
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __VNCHOOKS_H__
-#define __VNCHOOKS_H__
-
-extern "C" {
-#include <screenint.h>
- extern Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop);
-}
-
-#endif
+++ /dev/null
-/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
- */
-/* This is the xf86 module code for the vnc extension.
- */
-
-#include <rfb/Configuration.h>
-#include <rfb/Logger_stdio.h>
-#include <rfb/LogWriter.h>
-
-extern "C" {
-#define class c_class
-#define private c_private
-#define bool c_bool
-#define new c_new
-#include "xf86.h"
-#include "xf86Module.h"
-#undef class
-#undef private
-#undef bool
-#undef new
-
-using namespace rfb;
-
-extern void vncExtensionInit();
-static void vncExtensionInitWithParams(INITARGS);
-
-#ifdef XFree86LOADER
-
-static MODULESETUPPROTO(vncSetup);
-
-ExtensionModule vncExt =
-{
- vncExtensionInitWithParams,
- "VNC",
- NULL,
- NULL,
- NULL
-};
-
-static XF86ModuleVersionInfo vncVersRec =
-{
- "vnc",
- "Constantin Kaplinsky",
- MODINFOSTRING1,
- MODINFOSTRING2,
- XF86_VERSION_CURRENT,
- 1, 0, 0,
- ABI_CLASS_EXTENSION, /* needs the server extension ABI */
- ABI_EXTENSION_VERSION,
- MOD_CLASS_EXTENSION,
- {0,0,0,0}
-};
-
-XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };
-
-static pointer
-vncSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
- LoadExtension(&vncExt, FALSE);
- /* Need a non-NULL return value to indicate success */
- return (pointer)1;
-}
-
-static void vncExtensionInitWithParams(INITARGS)
-{
- rfb::initStdIOLoggers();
- rfb::LogWriter::setLogParams("*:stderr:30");
-
- for (int scr = 0; scr < screenInfo.numScreens; scr++) {
- ScrnInfoPtr pScrn = xf86Screens[scr];
-
- for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
- char* val = xf86FindOptionValue(pScrn->options, i.param->getName());
- if (val)
- i.param->setParam(val);
- }
- }
-
- vncExtensionInit();
-}
-
-#endif /* XFree86LOADER */
-}
--- /dev/null
+diff -up os/WaitFor.c.orig xorg/os/WaitFor.c
+--- os/WaitFor.c.orig 2008-01-28 10:20:35.000000000 +0100
++++ os/WaitFor.c 2008-01-28 10:21:08.000000000 +0100
+@@ -332,13 +332,11 @@ WaitForSomething(int *pClientsReady)
+
+ if (XFD_ANYSET (&devicesReadable) || XFD_ANYSET (&clientsReadable))
+ break;
+-#ifdef WIN32
+ /* Windows keyboard and mouse events are added to the input queue
+ in Block- and WakupHandlers. There is no device to check if
+ data is ready. So check here if new input is available */
+ if (*checkForInput[0] != *checkForInput[1])
+ return 0;
+-#endif
+ }
+ }
+
+diff -up mi/miinitext.c.orig xorg/mi/miinitext.c
+--- mi/miinitext.c.orig 2008-01-28 10:18:46.000000000 +0100
++++ mi/miinitext.c 2008-01-28 10:18:58.000000000 +0100
+@@ -289,6 +289,7 @@ extern void BigReqExtensionInit(INITARGS
+ #ifdef MITMISC
+ extern void MITMiscExtensionInit(INITARGS);
+ #endif
++extern void vncExtensionInit(INITARGS);
+ #ifdef XIDLE
+ extern void XIdleExtensionInit(INITARGS);
+ #endif
+@@ -560,6 +561,7 @@ InitExtensions(argc, argv)
+ #ifdef MITMISC
+ if (!noMITMiscExtension) MITMiscExtensionInit();
+ #endif
++ vncExtensionInit();
+ #ifdef XIDLE
+ if (!noXIdleExtension) XIdleExtensionInit();
+ #endif
+diff -up hw/Makefile.am.orig xorg/hw/Makefile.am
+--- hw/Makefile.am.orig 2008-01-28 10:18:46.000000000 +0100
++++ hw/Makefile.am 2008-01-28 10:18:58.000000000 +0100
+@@ -43,7 +43,8 @@ SUBDIRS = \
+ $(DMX_SUBDIRS) \
+ $(KDRIVE_SUBDIRS) \
+ $(XQUARTZ_SUBDIRS) \
+- $(XPRINT_SUBDIRS)
++ $(XPRINT_SUBDIRS) \
++ vnc
+
+ DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xgl xprint
+
+diff -up configure.ac.orig xorg/configure.ac
+--- configure.ac.orig 2008-01-28 10:18:45.000000000 +0100
++++ configure.ac 2008-01-28 10:18:58.000000000 +0100
+@@ -29,7 +29,6 @@ AC_PREREQ(2.57)
+ AC_INIT([xorg-server], 1.4.99.2, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+ AC_CONFIG_SRCDIR([Makefile.am])
+ AM_INIT_AUTOMAKE([dist-bzip2 foreign])
+-AM_MAINTAINER_MODE
+
+ dnl this gets generated by autoheader, and thus contains all the defines. we
+ dnl don't ever actually use it, internally.
+@@ -2173,6 +2172,7 @@ hw/dmx/input/Makefile
+ hw/dmx/glxProxy/Makefile
+ hw/dmx/Makefile
+ hw/vfb/Makefile
++hw/vnc/Makefile
+ hw/xgl/Makefile
+ hw/xgl/egl/Makefile
+ hw/xgl/egl/module/Makefile
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __REGIONHELPER_H__
+#define __REGIONHELPER_H__
+
+// RegionHelper is a class which helps in using X server regions by
+// automatically freeing them in the destructor. It also fixes a problem with
+// REGION_INIT when given an empty rectangle.
+
+// REGION_NULL was introduced in the Xorg tree as the way to initialise an
+// empty region. If it's not already defined do it the old way. Note that the
+// old way causes a segfault in the new tree...
+#ifndef REGION_NULL
+#define REGION_NULL(pScreen,pReg) REGION_INIT(pScreen,pReg,NullBox,0)
+#endif
+
+class RegionHelper {
+public:
+
+ // constructor from a single rect
+ RegionHelper(ScreenPtr pScreen_, BoxPtr rect, int size)
+ : pScreen(pScreen_), reg(0)
+ {
+ init(rect, size);
+ }
+
+ // constructor from an existing X server region
+ RegionHelper(ScreenPtr pScreen_, RegionPtr pRegion)
+ : pScreen(pScreen_), reg(®Rec)
+ {
+ REGION_NULL(pScreen, reg);
+ REGION_COPY(pScreen, reg, pRegion);
+ }
+
+ // constructor from an array of rectangles
+ RegionHelper(ScreenPtr pScreen_, int nrects, xRectanglePtr rects,
+ int ctype=CT_NONE)
+ : pScreen(pScreen_)
+ {
+ reg = RECTS_TO_REGION(pScreen, nrects, rects, ctype);
+ }
+
+ // constructor for calling init() later
+ RegionHelper(ScreenPtr pScreen_) : pScreen(pScreen_), reg(0) {
+ }
+
+ void init(BoxPtr rect, int size) {
+ reg = ®Rec;
+ if (!rect || (rect && (rect->x2 == rect->x1 || rect->y2 == rect->y1))) {
+ REGION_NULL(pScreen, reg);
+ } else {
+ REGION_INIT(pScreen, reg, rect, size);
+ }
+ }
+
+ // destructor frees as appropriate
+ ~RegionHelper() {
+ if (reg == ®Rec) {
+ REGION_UNINIT(pScreen, reg);
+ } else if (reg) {
+ REGION_DESTROY(pScreen, reg);
+ }
+ }
+ ScreenPtr pScreen;
+ RegionRec regRec;
+ RegionPtr reg;
+};
+
+#endif
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+//
+// XserverDesktop.cxx
+//
+
+#include <stdio.h>
+#include <strings.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <network/TcpSocket.h>
+#include <rfb/Exception.h>
+#include <rfb/VNCServerST.h>
+#include <rfb/HTTPServer.h>
+#include <rfb/LogWriter.h>
+#include <rfb/Configuration.h>
+#include "XserverDesktop.h"
+#include "vncExtInit.h"
+
+extern "C" {
+#define public c_public
+#define class c_class
+
+ // windowTable is in globals.h in XFree 4, but not in XFree 3 unfortunately
+extern WindowPtr *WindowTable;
+extern char *display;
+
+#include "inputstr.h"
+#include "servermd.h"
+#include "colormapst.h"
+#include "resource.h"
+#include "cursorstr.h"
+#include "windowstr.h"
+#define XK_CYRILLIC
+#include "keysym.h"
+#undef public
+#undef class
+}
+
+using namespace rfb;
+using namespace network;
+
+static LogWriter vlog("XserverDesktop");
+
+rfb::IntParameter deferUpdateTime("DeferUpdate",
+ "Time in milliseconds to defer updates",40);
+
+rfb::BoolParameter alwaysSetDeferUpdateTimer("AlwaysSetDeferUpdateTimer",
+ "Always reset the defer update timer on every change",false);
+
+IntParameter queryConnectTimeout("QueryConnectTimeout",
+ "Number of seconds to show the Accept Connection dialog before "
+ "rejecting the connection",
+ 10);
+
+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
+
+static rdr::U8 reverseBits[] = {
+ 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
+};
+
+
+class FileHTTPServer : public rfb::HTTPServer {
+public:
+ FileHTTPServer(XserverDesktop* d) : desktop(d) {}
+ virtual ~FileHTTPServer() {}
+
+ virtual rdr::InStream* getFile(const char* name, const char** contentType,
+ int* contentLength, time_t* lastModified)
+ {
+ if (name[0] != '/' || strstr(name, "..") != 0) {
+ vlog.info("http request was for invalid file name");
+ return 0;
+ }
+
+ if (strcmp(name, "/") == 0) name = "/index.vnc";
+
+ CharArray httpDirStr(httpDir.getData());
+ CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
+ sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
+ int fd = open(fname.buf, O_RDONLY);
+ if (fd < 0) return 0;
+ rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
+ *contentType = guessContentType(name, *contentType);
+ if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
+ is = new rdr::SubstitutingInStream(is, desktop, 20);
+ *contentType = "text/html";
+ } else {
+ struct stat st;
+ if (fstat(fd, &st) == 0) {
+ *contentLength = st.st_size;
+ *lastModified = st.st_mtime;
+ }
+ }
+ return is;
+ }
+
+ XserverDesktop* desktop;
+};
+
+
+XserverDesktop::XserverDesktop(ScreenPtr pScreen_,
+ network::TcpListener* listener_,
+ network::TcpListener* httpListener_,
+ const char* name, void* fbptr)
+ : pScreen(pScreen_), deferredUpdateTimer(0), dummyTimer(0),
+ server(0), httpServer(0),
+ listener(listener_), httpListener(httpListener_),
+ cmap(0), deferredUpdateTimerSet(false),
+ grabbing(false), ignoreHooks_(false), directFbptr(fbptr != 0),
+ oldButtonMask(0),
+ queryConnectId(0)
+{
+ int i;
+ format.depth = pScreen->rootDepth;
+ for (i = 0; i < screenInfo.numPixmapFormats; i++) {
+ if (screenInfo.formats[i].depth == format.depth) {
+ format.bpp = screenInfo.formats[i].bitsPerPixel;
+ break;
+ }
+ }
+ if (i == screenInfo.numPixmapFormats) {
+ fprintf(stderr,"no pixmap format for root depth???\n");
+ abort();
+ }
+ format.bigEndian = (screenInfo.imageByteOrder == MSBFirst);
+
+ VisualPtr vis;
+ for (i = 0; i < pScreen->numVisuals; i++) {
+ if (pScreen->visuals[i].vid == pScreen->rootVisual) {
+ vis = &pScreen->visuals[i];
+ break;
+ }
+ }
+ if (i == pScreen->numVisuals) {
+ fprintf(stderr,"no visual rec for root visual???\n");
+ abort();
+ }
+ format.trueColour = (vis->c_class == TrueColor);
+ if (!format.trueColour && format.bpp != 8)
+ throw rfb::Exception("X server uses unsupported visual");
+ format.redShift = ffs(vis->redMask) - 1;
+ format.greenShift = ffs(vis->greenMask) - 1;
+ format.blueShift = ffs(vis->blueMask) - 1;
+ format.redMax = vis->redMask >> format.redShift;
+ format.greenMax = vis->greenMask >> format.greenShift;
+ format.blueMax = vis->blueMask >> format.blueShift;
+
+ width_ = pScreen->width;
+ height_ = pScreen->height;
+ if (fbptr)
+ data = (rdr::U8*)fbptr;
+ else
+ data = new rdr::U8[pScreen->width * pScreen->height * (format.bpp/8)];
+ colourmap = this;
+
+ serverReset(pScreen);
+
+ server = new VNCServerST(name, this);
+ server->setPixelBuffer(this);
+ server->setQueryConnectionHandler(this);
+
+ if (httpListener)
+ httpServer = new FileHTTPServer(this);
+}
+
+XserverDesktop::~XserverDesktop()
+{
+ if (!directFbptr)
+ delete [] data;
+ TimerFree(deferredUpdateTimer);
+ TimerFree(dummyTimer);
+ delete httpServer;
+ delete server;
+}
+
+void XserverDesktop::serverReset(ScreenPtr pScreen_)
+{
+ pScreen = pScreen_;
+ XID* ids = new XID[pScreen->maxInstalledCmaps];
+ int nmaps = (*pScreen->ListInstalledColormaps)(pScreen, ids);
+ cmap = (ColormapPtr)LookupIDByType(ids[0], RT_COLORMAP);
+ delete [] ids;
+}
+
+char* XserverDesktop::substitute(const char* varName)
+{
+ if (strcmp(varName, "$$") == 0) {
+ return rfb::strDup("$");
+ }
+ if (strcmp(varName, "$PORT") == 0) {
+ char* str = new char[10];
+ sprintf(str, "%d", listener ? listener->getMyPort() : 0);
+ return str;
+ }
+ if (strcmp(varName, "$WIDTH") == 0) {
+ char* str = new char[10];
+ sprintf(str, "%d", width());
+ return str;
+ }
+ if (strcmp(varName, "$HEIGHT") == 0) {
+ char* str = new char[10];
+ sprintf(str, "%d", height());
+ return str;
+ }
+ if (strcmp(varName, "$APPLETWIDTH") == 0) {
+ char* str = new char[10];
+ sprintf(str, "%d", width());
+ return str;
+ }
+ if (strcmp(varName, "$APPLETHEIGHT") == 0) {
+ char* str = new char[10];
+ sprintf(str, "%d", height() + 32);
+ return str;
+ }
+ if (strcmp(varName, "$DESKTOP") == 0) {
+ return rfb::strDup(server->getName());
+ }
+ if (strcmp(varName, "$DISPLAY") == 0) {
+ struct utsname uts;
+ uname(&uts);
+ char* str = new char[256];
+ strncat(str, uts.nodename, 240);
+ strcat(str, ":");
+ strncat(str, display, 10);
+ return str;
+ }
+ if (strcmp(varName, "$USER") == 0) {
+ struct passwd* user = getpwuid(getuid());
+ return rfb::strDup(user ? user->pw_name : "?");
+ }
+ return 0;
+}
+
+rfb::VNCServerST::queryResult
+XserverDesktop::queryConnection(network::Socket* sock,
+ const char* userName,
+ char** reason) {
+ if (queryConnectId) {
+ *reason = strDup("Another connection is currently being queried.");
+ return rfb::VNCServerST::REJECT;
+ }
+ queryConnectAddress.replaceBuf(sock->getPeerAddress());
+ if (!userName)
+ userName = "(anonymous)";
+ queryConnectUsername.replaceBuf(strDup(userName));
+ queryConnectId = sock;
+ vncQueryConnect(this, sock);
+ return rfb::VNCServerST::PENDING;
+}
+
+
+void XserverDesktop::setColormap(ColormapPtr cmap_)
+{
+ if (cmap != cmap_) {
+ cmap = cmap_;
+ setColourMapEntries(0, 0);
+ }
+}
+
+void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef,
+ xColorItem* pdef)
+{
+ if (cmap != pColormap || ndef <= 0) return;
+
+ int first = pdef[0].pixel;
+ int n = 1;
+
+ for (int i = 1; i < ndef; i++) {
+ if (first + n == pdef[i].pixel) {
+ n++;
+ } else {
+ setColourMapEntries(first, n);
+ first = pdef[i].pixel;
+ n = 1;
+ }
+ }
+ setColourMapEntries(first, n);
+}
+
+void XserverDesktop::setColourMapEntries(int firstColour, int nColours)
+{
+ try {
+ server->setColourMapEntries(firstColour, nColours);
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::setColourMapEntries: %s",e.str());
+ }
+}
+
+void XserverDesktop::bell()
+{
+ server->bell();
+}
+
+void XserverDesktop::serverCutText(const char* str, int len)
+{
+ try {
+ server->serverCutText(str, len);
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::serverCutText: %s",e.str());
+ }
+}
+
+void XserverDesktop::setCursor(CursorPtr cursor)
+{
+ try {
+ int w = cursor->bits->width;
+ int h = cursor->bits->height;
+ rdr::U8* cursorData = new rdr::U8[w * h * (getPF().bpp / 8)];
+
+ xColorItem fg, bg;
+ fg.red = cursor->foreRed;
+ fg.green = cursor->foreGreen;
+ fg.blue = cursor->foreBlue;
+ FakeAllocColor(cmap, &fg);
+ bg.red = cursor->backRed;
+ bg.green = cursor->backGreen;
+ bg.blue = cursor->backBlue;
+ FakeAllocColor(cmap, &bg);
+ FakeFreeColor(cmap, fg.pixel);
+ FakeFreeColor(cmap, bg.pixel);
+
+ int xMaskBytesPerRow = BitmapBytePad(w);
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ int byte = y * xMaskBytesPerRow + x / 8;
+#if (BITMAP_BIT_ORDER == MSBFirst)
+ int bit = 7 - x % 8;
+#else
+ int bit = x % 8;
+#endif
+ switch (getPF().bpp) {
+ case 8:
+ ((rdr::U8*)cursorData)[y * w + x]
+ = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+ break;
+ case 16:
+ ((rdr::U16*)cursorData)[y * w + x]
+ = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+ break;
+ case 32:
+ ((rdr::U32*)cursorData)[y * w + x]
+ = (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel;
+ break;
+ }
+ }
+ }
+
+ int rfbMaskBytesPerRow = (w + 7) / 8;
+
+ rdr::U8* cursorMask = new rdr::U8[rfbMaskBytesPerRow * h];
+
+ for (int j = 0; j < h; j++) {
+ for (int i = 0; i < rfbMaskBytesPerRow; i++)
+#if (BITMAP_BIT_ORDER == MSBFirst)
+ cursorMask[j * rfbMaskBytesPerRow + i]
+ = cursor->bits->mask[j * xMaskBytesPerRow + i];
+#else
+ cursorMask[j * rfbMaskBytesPerRow + i]
+ = reverseBits[cursor->bits->mask[j * xMaskBytesPerRow + i]];
+#endif
+ }
+
+ server->setCursor(cursor->bits->width, cursor->bits->height,
+ Point(cursor->bits->xhot, cursor->bits->yhot),
+ cursorData, cursorMask);
+ server->tryUpdate();
+ delete [] cursorData;
+ delete [] cursorMask;
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::setCursor: %s",e.str());
+ }
+}
+
+static void printRegion(RegionPtr reg)
+{
+ int nrects = REGION_NUM_RECTS(reg);
+
+ fprintf(stderr,"Region num rects %2d extents %3d,%3d %3dx%3d\n",nrects,
+ (REGION_EXTENTS(pScreen,reg))->x1,
+ (REGION_EXTENTS(pScreen,reg))->y1,
+ (REGION_EXTENTS(pScreen,reg))->x2-(REGION_EXTENTS(pScreen,reg))->x1,
+ (REGION_EXTENTS(pScreen,reg))->y2-(REGION_EXTENTS(pScreen,reg))->y1);
+
+ for (int i = 0; i < nrects; i++) {
+ fprintf(stderr," rect %3d,%3d %3dx%3d\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);
+ }
+}
+
+CARD32 XserverDesktop::deferredUpdateTimerCallback(OsTimerPtr timer,
+ CARD32 now, pointer arg)
+{
+ XserverDesktop* desktop = (XserverDesktop*)arg;
+ desktop->deferredUpdateTimerSet = false;
+ try {
+ desktop->server->tryUpdate();
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::deferredUpdateTimerCallback: %s",e.str());
+ }
+ return 0;
+}
+
+void XserverDesktop::deferUpdate()
+{
+ if (deferUpdateTime != 0) {
+ if (!deferredUpdateTimerSet || alwaysSetDeferUpdateTimer) {
+ deferredUpdateTimerSet = true;
+ deferredUpdateTimer = TimerSet(deferredUpdateTimer, 0,
+ deferUpdateTime,
+ deferredUpdateTimerCallback, this);
+ }
+ } else {
+ server->tryUpdate();
+ }
+}
+
+void XserverDesktop::add_changed(RegionPtr reg)
+{
+ if (ignoreHooks_) return;
+ if (grabbing) return;
+ try {
+ rfb::Region rfbReg;
+ rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, reg),
+ REGION_NUM_RECTS(reg),
+ (ShortRect*)REGION_RECTS(reg));
+ server->add_changed(rfbReg);
+ deferUpdate();
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::add_changed: %s",e.str());
+ }
+}
+
+void XserverDesktop::add_copied(RegionPtr dst, int dx, int dy)
+{
+ if (ignoreHooks_) return;
+ if (grabbing) return;
+ try {
+ rfb::Region rfbReg;
+ rfbReg.setExtentsAndOrderedRects((ShortRect*)REGION_EXTENTS(pScreen, dst),
+ REGION_NUM_RECTS(dst),
+ (ShortRect*)REGION_RECTS(dst));
+ server->add_copied(rfbReg, rfb::Point(dx, dy));
+ deferUpdate();
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::add_copied: %s",e.str());
+ }
+}
+
+void XserverDesktop::positionCursor()
+{
+ if (!cursorPos.equals(oldCursorPos)) {
+ oldCursorPos = cursorPos;
+ (*pScreen->SetCursorPosition) (pScreen, cursorPos.x, cursorPos.y, FALSE);
+ server->setCursorPos(cursorPos);
+ server->tryUpdate();
+ }
+}
+
+void XserverDesktop::blockHandler(fd_set* fds)
+{
+ try {
+ ScreenPtr screenWithCursor = GetCurrentRootWindow()->drawable.pScreen;
+ if (screenWithCursor == pScreen) {
+ int x, y;
+ GetSpritePosition(&x, &y);
+ if (x != cursorPos.x || y != cursorPos.y) {
+ cursorPos = oldCursorPos = Point(x, y);
+ server->setCursorPos(cursorPos);
+ server->tryUpdate();
+ }
+ }
+
+ if (listener)
+ FD_SET(listener->getFd(), fds);
+ if (httpListener)
+ FD_SET(httpListener->getFd(), fds);
+
+ std::list<Socket*> sockets;
+ server->getSockets(&sockets);
+ std::list<Socket*>::iterator i;
+ for (i = sockets.begin(); i != sockets.end(); i++) {
+ int fd = (*i)->getFd();
+ if ((*i)->isShutdown()) {
+ vlog.debug("client gone, sock %d",fd);
+ server->removeSocket(*i);
+ vncClientGone(fd);
+ delete (*i);
+ } else {
+ FD_SET(fd, fds);
+ }
+ }
+ if (httpServer) {
+ httpServer->getSockets(&sockets);
+ for (i = sockets.begin(); i != sockets.end(); i++) {
+ int fd = (*i)->getFd();
+ if ((*i)->isShutdown()) {
+ vlog.debug("http client gone, sock %d",fd);
+ httpServer->removeSocket(*i);
+ delete (*i);
+ } else {
+ FD_SET(fd, fds);
+ }
+ }
+ }
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::blockHandler: %s",e.str());
+ }
+}
+
+static CARD32 dummyTimerCallback(OsTimerPtr timer, CARD32 now, pointer arg) {
+ return 0;
+}
+
+void XserverDesktop::wakeupHandler(fd_set* fds, int nfds)
+{
+ try {
+ if (nfds >= 1) {
+
+ if (listener) {
+ if (FD_ISSET(listener->getFd(), fds)) {
+ FD_CLR(listener->getFd(), fds);
+ Socket* sock = listener->accept();
+ server->addSocket(sock);
+ vlog.debug("new client, sock %d",sock->getFd());
+ }
+ }
+
+ if (httpListener) {
+ if (FD_ISSET(httpListener->getFd(), fds)) {
+ FD_CLR(httpListener->getFd(), fds);
+ Socket* sock = httpListener->accept();
+ httpServer->addSocket(sock);
+ vlog.debug("new http client, sock %d",sock->getFd());
+ }
+ }
+
+ std::list<Socket*> sockets;
+ server->getSockets(&sockets);
+ std::list<Socket*>::iterator i;
+ for (i = sockets.begin(); i != sockets.end(); i++) {
+ int fd = (*i)->getFd();
+ if (FD_ISSET(fd, fds)) {
+ FD_CLR(fd, fds);
+ server->processSocketEvent(*i);
+ }
+ }
+
+ if (httpServer) {
+ httpServer->getSockets(&sockets);
+ for (i = sockets.begin(); i != sockets.end(); i++) {
+ int fd = (*i)->getFd();
+ if (FD_ISSET(fd, fds)) {
+ FD_CLR(fd, fds);
+ httpServer->processSocketEvent(*i);
+ }
+ }
+ }
+
+ positionCursor();
+ }
+
+ int timeout = server->checkTimeouts();
+ if (timeout > 0) {
+ // set a dummy timer just so we are guaranteed be called again next time.
+ dummyTimer = TimerSet(dummyTimer, 0, timeout,
+ dummyTimerCallback, 0);
+ }
+
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::wakeupHandler: %s",e.str());
+ }
+}
+
+void XserverDesktop::addClient(Socket* sock, bool reverse)
+{
+ vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
+ server->addSocket(sock, reverse);
+}
+
+void XserverDesktop::disconnectClients()
+{
+ vlog.debug("disconnecting all clients");
+ return server->closeClients("Disconnection from server end");
+}
+
+
+int XserverDesktop::getQueryTimeout(void* opaqueId,
+ const char** address,
+ const char** username)
+{
+ if (opaqueId && queryConnectId == opaqueId) {
+ vlog.info("address=%s, username=%s, timeout=%d",
+ queryConnectAddress.buf, queryConnectUsername.buf,
+ (int)queryConnectTimeout);
+ if (address) *address = queryConnectAddress.buf;
+ if (username) *username = queryConnectUsername.buf;
+ return queryConnectTimeout;
+ }
+ return 0;
+}
+
+void XserverDesktop::approveConnection(void* opaqueId, bool accept,
+ const char* rejectMsg)
+{
+ if (queryConnectId == opaqueId) {
+ server->approveConnection((network::Socket*)opaqueId, accept, rejectMsg);
+ queryConnectId = 0;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// SDesktop callbacks
+
+
+void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
+{
+ xEvent ev;
+ DevicePtr dev = LookupPointerDevice();
+
+ // SetCursorPosition seems to be very expensive (at least on XFree86 3.3.6
+ // for S3), so we delay calling it until positionCursor() is called at the
+ // end of processing a load of RFB.
+ //(*pScreen->SetCursorPosition) (pScreen, pos.x, pos.y, FALSE);
+
+ NewCurrentScreen(pScreen, pos.x, pos.y);
+
+ ev.u.u.type = MotionNotify;
+ ev.u.u.detail = 0;
+ ev.u.keyButtonPointer.rootX = pos.x;
+ ev.u.keyButtonPointer.rootY = pos.y;
+ ev.u.keyButtonPointer.time = GetTimeInMillis();
+
+ if (!pos.equals(cursorPos))
+ (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
+
+ for (int i = 0; i < 5; i++) {
+ if ((buttonMask ^ oldButtonMask) & (1<<i)) {
+ // Do not use the pointer mapping. Treat VNC buttons as logical
+ // buttons.
+ ev.u.u.detail = i + 1;
+ ev.u.u.type = (buttonMask & (1<<i)) ? ButtonPress : ButtonRelease;
+ (*dev->processInputProc)(&ev, (DeviceIntPtr)dev, 1);
+ }
+ }
+
+ cursorPos = pos;
+ oldButtonMask = buttonMask;
+}
+
+void XserverDesktop::clientCutText(const char* str, int len)
+{
+ vncClientCutText(str, len);
+}
+
+void XserverDesktop::grabRegion(const rfb::Region& region)
+{
+ if (directFbptr) return;
+ if (!pScreen->GetImage) {
+ vlog.error("VNC error: pScreen->GetImage == 0");
+ return;
+ }
+
+ grabbing = true;
+
+ int bytesPerPixel = format.bpp/8;
+ int bytesPerRow = pScreen->width * bytesPerPixel;
+
+ std::vector<rfb::Rect> rects;
+ std::vector<rfb::Rect>::iterator i;
+ region.get_rects(&rects);
+ for (i = rects.begin(); i != rects.end(); i++) {
+ for (int y = i->tl.y; y < i->br.y; y++) {
+ (*pScreen->GetImage) ((DrawablePtr)WindowTable[pScreen->myNum],
+ i->tl.x, y, i->width(), 1,
+ ZPixmap, (unsigned long)~0L,
+ ((char*)data
+ + y * bytesPerRow + i->tl.x * bytesPerPixel));
+ }
+ }
+ grabbing = false;
+}
+
+void XserverDesktop::lookup(int index, int* r, int* g, int* b)
+{
+ if ((cmap->c_class | DynamicClass) == DirectColor) {
+ VisualPtr v = cmap->pVisual;
+ *r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red;
+ *g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green;
+ *b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue;
+ } else {
+ EntryPtr pent;
+ pent = (EntryPtr)&cmap->red[index];
+ 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;
+ }
+ }
+}
+
+//
+// Keyboard handling
+//
+
+#define IS_PRESSED(keyc, keycode) \
+ ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
+
+// ModifierState is a class which helps simplify generating a "fake" press
+// or release of shift, ctrl, alt, etc. An instance of the class is created
+// for every modifier which may need to be pressed or released. Then either
+// press() or release() may be called to make sure that the corresponding keys
+// are in the right state. The destructor of the class automatically reverts
+// to the previous state. Each modifier may have multiple keys associated with
+// it, so in the case of a fake release, this may involve releasing more than
+// one key.
+
+class ModifierState {
+public:
+ ModifierState(DeviceIntPtr dev_, int modIndex_)
+ : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false)
+ {
+ }
+ ~ModifierState() {
+ for (int i = 0; i < nKeys; i++)
+ generateXKeyEvent(keys[i], !pressed);
+ delete [] keys;
+ }
+ void press() {
+ KeyClassPtr keyc = dev->key;
+ if (!(keyc->state & (1<<modIndex))) {
+ tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier],
+ true);
+ pressed = true;
+ }
+ }
+ void release() {
+ KeyClassPtr keyc = dev->key;
+ if (keyc->state & (1<<modIndex)) {
+ for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+ int keycode
+ = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k];
+ if (keycode && IS_PRESSED(keyc, keycode))
+ tempKeyEvent(keycode, false);
+ }
+ }
+ }
+private:
+ void tempKeyEvent(int keycode, bool down) {
+ if (keycode) {
+ if (!keys) keys = new int[dev->key->maxKeysPerModifier];
+ keys[nKeys++] = keycode;
+ generateXKeyEvent(keycode, down);
+ }
+ }
+ void generateXKeyEvent(int keycode, bool down) {
+ xEvent ev;
+ ev.u.u.type = down ? KeyPress : KeyRelease;
+ ev.u.u.detail = keycode;
+ ev.u.keyButtonPointer.time = GetTimeInMillis();
+ (*dev->c_public.processInputProc)(&ev, dev, 1);
+ vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up");
+ }
+ DeviceIntPtr dev;
+ int modIndex;
+ int nKeys;
+ int* keys;
+ bool pressed;
+};
+
+
+// altKeysym is a table of alternative keysyms which have the same meaning.
+
+struct altKeysym_t {
+ KeySym a, b;
+};
+
+altKeysym_t altKeysym[] = {
+ { XK_Shift_L, XK_Shift_R },
+ { XK_Control_L, XK_Control_R },
+ { XK_Meta_L, XK_Meta_R },
+ { XK_Alt_L, XK_Alt_R },
+ { XK_Super_L, XK_Super_R },
+ { XK_Hyper_L, XK_Hyper_R },
+ { XK_KP_Space, XK_space },
+ { XK_KP_Tab, XK_Tab },
+ { XK_KP_Enter, XK_Return },
+ { XK_KP_F1, XK_F1 },
+ { XK_KP_F2, XK_F2 },
+ { XK_KP_F3, XK_F3 },
+ { XK_KP_F4, XK_F4 },
+ { XK_KP_Home, XK_Home },
+ { XK_KP_Left, XK_Left },
+ { XK_KP_Up, XK_Up },
+ { XK_KP_Right, XK_Right },
+ { XK_KP_Down, XK_Down },
+ { XK_KP_Page_Up, XK_Page_Up },
+ { XK_KP_Page_Down, XK_Page_Down },
+ { XK_KP_End, XK_End },
+ { XK_KP_Begin, XK_Begin },
+ { XK_KP_Insert, XK_Insert },
+ { XK_KP_Delete, XK_Delete },
+ { XK_KP_Equal, XK_equal },
+ { XK_KP_Multiply, XK_asterisk },
+ { XK_KP_Add, XK_plus },
+ { XK_KP_Separator, XK_comma },
+ { XK_KP_Subtract, XK_minus },
+ { XK_KP_Decimal, XK_period },
+ { XK_KP_Divide, XK_slash },
+ { XK_KP_0, XK_0 },
+ { XK_KP_1, XK_1 },
+ { XK_KP_2, XK_2 },
+ { XK_KP_3, XK_3 },
+ { XK_KP_4, XK_4 },
+ { XK_KP_5, XK_5 },
+ { XK_KP_6, XK_6 },
+ { XK_KP_7, XK_7 },
+ { XK_KP_8, XK_8 },
+ { XK_KP_9, XK_9 },
+};
+
+// keyEvent() - work out the best keycode corresponding to the keysym sent by
+// the viewer. This is non-trivial because we can't assume much about the
+// local keyboard layout. We must also find out which column of the keyboard
+// mapping the keysym is in, and alter the shift state appropriately. Column 0
+// means both shift and "mode_switch" (AltGr) must be released, column 1 means
+// shift must be pressed and mode_switch released, column 2 means shift must be
+// released and mode_switch pressed, and column 3 means both shift and
+// mode_switch must be pressed.
+
+void XserverDesktop::keyEvent(rdr::U32 keysym, bool down)
+{
+ if (keysym == XK_Caps_Lock) {
+ vlog.debug("Ignoring caps lock");
+ return;
+ }
+ DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice();
+ KeyClassPtr keyc = dev->key;
+ KeySymsPtr keymap = &keyc->curKeySyms;
+
+ // find which modifier Mode_switch is on.
+ int modeSwitchMapIndex = 0;
+ for (int i = 3; i < 8; i++) {
+ for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+ int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k];
+ for (int j = 0; j < keymap->mapWidth; j++) {
+ if (keycode != 0 &&
+ keymap->map[(keycode - keymap->minKeyCode)
+ * keymap->mapWidth + j] == XK_Mode_switch)
+ {
+ modeSwitchMapIndex = i;
+ break;
+ }
+ }
+ }
+ }
+
+ int col = 0;
+ if (keyc->state & (1<<ShiftMapIndex)) col |= 1;
+ if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2;
+
+ int kc = KeysymToKeycode(keymap, keysym, &col);
+
+ // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a
+ // local shifted Tab regardless of what the "shifted Tab" keysym is on the
+ // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab
+ // keysym, and quite possibly some others too). We never get ISO_Left_Tab
+ // here because it's already been translated in VNCSConnectionST.
+ if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex)))
+ col |= 1;
+
+ if (kc == 0) {
+ // Not a direct match in the local keyboard mapping. Check for alternative
+ // keysyms with the same meaning.
+ for (int i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
+ if (keysym == altKeysym[i].a)
+ kc = KeysymToKeycode(keymap, altKeysym[i].b, &col);
+ else if (keysym == altKeysym[i].b)
+ kc = KeysymToKeycode(keymap, altKeysym[i].a, &col);
+ if (kc) break;
+ }
+ }
+
+ if (kc == 0) {
+ // Last resort - dynamically add a new key to the keyboard mapping.
+ for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) {
+ if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) {
+ keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym;
+ col = 0;
+ SendMappingNotify(MappingKeyboard, kc, 1, serverClient);
+ vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc);
+ break;
+ }
+ }
+ if (kc < keymap->minKeyCode) {
+ vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym);
+ return;
+ }
+ }
+
+ // See if it's a modifier key. If so, then don't do any auto-repeat, because
+ // the X server will translate each press into a release followed by a press.
+ for (int i = 0; i < 8; i++) {
+ for (int k = 0; k < keyc->maxKeysPerModifier; k++) {
+ if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] &&
+ IS_PRESSED(keyc,kc) && down)
+ return;
+ }
+ }
+
+ ModifierState shift(dev, ShiftMapIndex);
+ ModifierState modeSwitch(dev, modeSwitchMapIndex);
+ if (down) {
+ if (col & 1)
+ shift.press();
+ else
+ shift.release();
+ if (modeSwitchMapIndex) {
+ if (col & 2)
+ modeSwitch.press();
+ else
+ modeSwitch.release();
+ }
+ }
+ vlog.debug("keycode %d %s", kc, down ? "down" : "up");
+ xEvent ev;
+ ev.u.u.type = down ? KeyPress : KeyRelease;
+ ev.u.u.detail = kc;
+ ev.u.keyButtonPointer.time = GetTimeInMillis();
+ (*dev->c_public.processInputProc)(&ev, dev, 1);
+}
+
+
+void XConvertCase(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;
+ }
+}
+
+static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
+{
+ register int per = keymap->mapWidth;
+ register KeySym *syms;
+ KeySym lsym, usym;
+
+ if ((col < 0) || ((col >= per) && (col > 3)) ||
+ (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
+ return NoSymbol;
+
+ syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
+ if (col < 4) {
+ if (col > 1) {
+ while ((per > 2) && (syms[per - 1] == NoSymbol))
+ per--;
+ if (per < 3)
+ col -= 2;
+ }
+ if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
+ XConvertCase(syms[col&~1], &lsym, &usym);
+ if (!(col & 1))
+ return lsym;
+ // I'm commenting out this logic because it's incorrect even though it
+ // was copied from the Xlib sources. The X protocol book quite clearly
+ // states that where a group consists of element 1 being a non-alphabetic
+ // keysym and element 2 being NoSymbol that you treat the second element
+ // as being the same as the first. This also tallies with the behaviour
+ // produced by the installed Xlib on my linux box (I believe this is
+ // because it uses some XKB code rather than the original Xlib code -
+ // compare XKBBind.c with KeyBind.c in lib/X11).
+ // else if (usym == lsym)
+ // return NoSymbol;
+ else
+ return usym;
+ }
+ }
+ return syms[col];
+}
+
+// KeysymToKeycode() - find the keycode and column corresponding to the given
+// keysym. The value of col passed in should be the column determined from the
+// current shift state. If the keysym can be found in that column we prefer
+// that to finding it in a different column (which would require fake events to
+// alter the shift state).
+
+static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
+{
+ register int i, j;
+
+ j = *col;
+ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
+ if (KeyCodetoKeySym(keymap, i, j) == ks)
+ return i;
+ }
+
+ for (j = 0; j < keymap->mapWidth; j++) {
+ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
+ if (KeyCodetoKeySym(keymap, i, j) == ks) {
+ *col = j;
+ return i;
+ }
+ }
+ }
+ return 0;
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+//
+// XserverDesktop.h
+//
+
+#ifndef __XSERVERDESKTOP_H__
+#define __XSERVERDESKTOP_H__
+
+#include <rfb/SDesktop.h>
+#include <rfb/HTTPServer.h>
+#include <rfb/PixelBuffer.h>
+#include <rfb/Configuration.h>
+#include <rfb/VNCServerST.h>
+#include <rdr/SubstitutingInStream.h>
+
+extern "C" {
+#define class c_class;
+#include <scrnintstr.h>
+#include <os.h>
+#undef class
+}
+
+namespace rfb {
+ class VNCServerST;
+}
+
+namespace network { class TcpListener; class Socket; }
+
+class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
+ public rfb::ColourMap, public rdr::Substitutor,
+ public rfb::VNCServerST::QueryConnectionHandler {
+public:
+
+ XserverDesktop(ScreenPtr pScreen, network::TcpListener* listener,
+ network::TcpListener* httpListener_,
+ const char* name, void* fbptr);
+ virtual ~XserverDesktop();
+
+ // methods called from X server code
+ void serverReset(ScreenPtr pScreen);
+ void setColormap(ColormapPtr cmap);
+ void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef);
+ void bell();
+ void serverCutText(const char* str, int len);
+ void setCursor(CursorPtr cursor);
+ void add_changed(RegionPtr reg);
+ void add_copied(RegionPtr dst, int dx, int dy);
+ void positionCursor();
+ void ignoreHooks(bool b) { ignoreHooks_ = b; }
+ void blockHandler(fd_set* fds);
+ void wakeupHandler(fd_set* fds, int nfds);
+ void addClient(network::Socket* sock, bool reverse);
+ void disconnectClients();
+
+ // QueryConnect methods called from X server code
+ // getQueryTimeout()
+ // Returns the timeout associated with a particular
+ // connection, identified by an opaque Id passed to the
+ // X code earlier. Also optionally gets the address and
+ // name associated with that connection.
+ // Returns zero if the Id is not recognised.
+ int getQueryTimeout(void* opaqueId,
+ const char** address=0,
+ const char** username=0);
+
+ // approveConnection()
+ // Used by X server code to supply the result of a query.
+ void approveConnection(void* opaqueId, bool accept,
+ const char* rejectMsg=0);
+
+ // rfb::SDesktop callbacks
+ virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
+ virtual void keyEvent(rdr::U32 key, bool down);
+ virtual void clientCutText(const char* str, int len);
+ virtual rfb::Point getFbSize() { return rfb::Point(width(), height()); }
+
+ // rfb::PixelBuffer callbacks
+ virtual void grabRegion(const rfb::Region& r);
+
+ // rfb::ColourMap callbacks
+ virtual void lookup(int index, int* r, int* g, int* b);
+
+ // rdr::Substitutor callback
+ virtual char* substitute(const char* varName);
+
+ // rfb::VNCServerST::QueryConnectionHandler callback
+ virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
+ const char* userName,
+ char** reason);
+
+private:
+ void setColourMapEntries(int firstColour, int nColours);
+ static CARD32 deferredUpdateTimerCallback(OsTimerPtr timer, CARD32 now,
+ pointer arg);
+ void deferUpdate();
+ ScreenPtr pScreen;
+ OsTimerPtr deferredUpdateTimer, dummyTimer;
+ rfb::VNCServerST* server;
+ rfb::HTTPServer* httpServer;
+ network::TcpListener* listener;
+ network::TcpListener* httpListener;
+ ColormapPtr cmap;
+ bool deferredUpdateTimerSet;
+ bool grabbing;
+ bool ignoreHooks_;
+ bool directFbptr;
+ int oldButtonMask;
+ rfb::Point cursorPos, oldCursorPos;
+
+ void* queryConnectId;
+ rfb::CharArray queryConnectAddress;
+ rfb::CharArray queryConnectUsername;
+};
+#endif
--- /dev/null
+.TH Xvnc 1 "17 Apr 2006" "TightVNC" "Virtual Network Computing"
+.SH NAME
+Xvnc \- the X VNC server
+.SH SYNOPSIS
+.B Xvnc
+.RI [ options ]
+.RI : display#
+.SH DESCRIPTION
+.B Xvnc
+is the X VNC (Virtual Network Computing) server. It is based on a standard X
+server, but it has a "virtual" screen rather than a physical one. X
+applications display themselves on it as if it were a normal X display, but
+they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1).
+
+So Xvnc is really two servers in one. To the applications it is an X server,
+and to the remote VNC users it is a VNC server. By convention we have arranged
+that the VNC server display number will be the same as the X server display
+number, which means you can use eg. snoopy:2 to refer to display 2 on machine
+"snoopy" in both the X world and the VNC world.
+
+The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This
+sets up the environment appropriately and runs some X applications to get you
+going. See the manual page for \fBvncserver\fP(1) for more information.
+
+.SH OPTIONS
+.B Xvnc
+takes lots of options - running \fBXvnc -help\fP gives a list. Many of these
+are standard X server options, which are described in the \fBXserver\fP(1)
+manual page. In addition to options which can only be set via the
+command-line, there are also "parameters" which can be set both via the
+command-line and through the \fBvncconfig\fP(1) program.
+
+.TP
+.B \-geometry \fIwidth\fPx\fIheight\fP
+Specify the size of the desktop to be created. Default is 1024x768.
+
+.TP
+.B \-depth \fIdepth\fP
+Specify the pixel depth in bits of the desktop to be created. Default is 16,
+other possible values are 8, 15, and 24 - anything else is likely to cause
+strange behaviour by applications.
+
+.TP
+.B \-pixelformat \fIformat\fP
+Specify pixel format for server to use (BGRnnn or RGBnnn). The default for
+depth 8 is BGR233 (meaning the most significant two bits represent blue, the
+next three green, and the least significant three represent red), the default
+for depth 16 is RGB565 and for depth 24 is RGB888.
+
+.TP
+.B \-cc 3
+As an alternative to the default TrueColor visual, this allows you to run an
+Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
+palette), which can be useful for running some old X applications which only
+work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor)
+for the \-cc option may result in strange behaviour, and PseudoColor desktops
+must be 8 bits deep (i.e. \fB-depth 8\fP).
+
+.TP
+.B \-inetd
+This significantly changes Xvnc's behaviour so that it can be launched from
+inetd. See the section below on usage with inetd.
+
+.TP
+.B \-help
+List all the options and parameters
+
+.SH PARAMETERS
+VNC parameters can be set both via the command-line and through the
+\fBvncconfig\fP(1) program, and with a VNC-enabled XFree86 server via Options
+entries in the XF86Config file.
+
+Parameters can be turned on with -\fIparam\fP or off with
+-\fIparam\fP=0. Parameters which take a value can be specified as
+-\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP
+-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are
+case-insensitive.
+
+.TP
+.B \-desktop \fIdesktop-name\fP
+Each desktop has a name which may be displayed by the viewer. It defaults to
+"x11".
+
+.TP
+.B \-rfbport \fIport\fP
+Specifies the TCP port on which Xvnc listens for connections from viewers (the
+protocol used in VNC is called RFB - "remote framebuffer"). The default is
+5900 plus the display number.
+
+.TP
+.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
+
+Time in milliseconds to wait for a viewer which is blocking Xvnc. This is
+necessary because Xvnc is single-threaded and sometimes blocks until the viewer
+has finished sending or receiving a message - note that this does not mean an
+update will be aborted after this time. Default is 20000 (20 seconds).
+
+.TP
+.B \-httpd \fIdirectory\fP
+Run a mini-HTTP server which serves files from the given directory. Normally
+the directory will contain the classes for the Java viewer. In addition, files
+with a .vnc extension will have certain substitutions made so that a single
+installation of the Java VNC viewer can be served by separate instances of
+Xvnc.
+
+.TP
+.B \-httpPort \fIport\fP
+Specifies the port on which the mini-HTTP server runs. Default is 5800 plus
+the display number.
+
+.TP
+.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
+Specifies the file containing the password used to authenticate viewers. The
+file is accessed each time a connection comes in, so it can be changed on the
+fly via \fBvncpasswd\fP(1).
+
+.TP
+.B \-deferUpdate \fItime\fP
+Xvnc uses a "deferred update" mechanism which enhances performance in many
+cases. After any change to the framebuffer, Xvnc waits for this number of
+milliseconds (default 40) before sending an update to any waiting clients. This
+means that more changes tend to get coalesced together in a single
+update. Setting it to 0 results in the same behaviour as earlier versions of
+Xvnc, where the first change to the framebuffer causes an immediate update to
+any waiting clients.
+
+.TP
+.B \-SendCutText
+Send clipboard changes to clients (default is on). Note that you must also run
+\fBvncconfig\fP(1) to get the clipboard to work.
+
+.TP
+.B \-AcceptCutText
+Accept clipboard updates from clients (default is on). Note that you must also
+run \fBvncconfig\fP(1) to get the clipboard to work.
+
+.TP
+.B \-AcceptPointerEvents
+Accept pointer press and release events from clients (default is on).
+
+.TP
+.B \-AcceptKeyEvents
+Accept key press and release events from clients (default is on).
+
+.TP
+.B \-DisconnectClients
+Disconnect existing clients if an incoming connection is non-shared (default is
+on). If \fBDisconnectClients\fP is false, then a new non-shared connection will
+be refused while there is a client active. When combined with
+\fBNeverShared\fP this means only one client is allowed at a time.
+
+.TP
+.B \-NeverShared
+Never treat incoming connections as shared, regardless of the client-specified
+setting (default is off).
+
+.TP
+.B \-AlwaysShared
+Always treat incoming connections as shared, regardless of the client-specified
+setting (default is off).
+
+.TP
+.B \-Protocol3.3
+Always use protocol version 3.3 for backwards compatibility with badly-behaved
+clients (default is off).
+
+.TP
+.B \-CompareFB
+Perform pixel comparison on framebuffer to reduce unnecessary updates (default
+is on).
+
+.TP
+.B \-SecurityTypes \fIsec-types\fP
+Specify which security schemes to use separated by commas. At present only
+"None" and "VncAuth" are supported. The default is "VncAuth" - note that if
+you want a server which does not require a password, you must set this
+parameter to "None".
+
+.TP
+.B \-IdleTimeout \fIseconds\fP
+The number of seconds after which an idle VNC connection will be dropped
+(default is 0, which means that idle connections will never be dropped).
+
+.TP
+.B \-QueryConnect
+Prompts the user of the desktop to explicitly accept or reject incoming
+connections. This is most useful when using the vnc.so module or
+\fBx0vncserver\fP(1) program to access an existing X desktop via VNC.
+
+The \fBvncconfig\fP(1) program must be running on the desktop in order for
+QueryConnect to be supported by the \fBvnc.so\fP(1) module or
+\fBXvnc\fP(1) program. The \fBx0vncserver\fP(1) program does not require
+\fBvncconfig\fP(1) to be running.
+
+.TP
+.B \-localhost
+Only allow connections from the same machine. Useful if you use SSH and want to
+stop non-SSH connections from any other hosts. See the guide to using VNC with
+SSH on the web site.
+
+.TP
+.B \-log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
+Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP or
+\fBstdout\fP, and \fIlevel\fP is between 0 and 100, 100 meaning most verbose
+output. \fIlogname\fP is usually \fB*\fP meaning all, but you can target a
+specific source file if you know the name of its "LogWriter". Default is
+\fB*:stderr:30\fP.
+
+.TP
+.B \-RemapKeys \fImapping
+Sets up a keyboard mapping.
+.I mapping
+is a comma-separated string of character mappings, each of the form
+.IR char -> char ,
+or
+.IR char <> char ,
+where
+.I char
+is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following:
+.IP "" 10
+RemapKeys=0x22<>0x40
+
+.SH USAGE WITH INETD
+By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
+on demand when a connection comes in, rather than having to be started
+manually. When given the \fB-inetd\fP option, instead of listening for TCP
+connections on a given port it uses its standard input and standard output.
+There are two modes controlled by the wait/nowait entry in the inetd.conf file.
+
+In the nowait mode, Xvnc uses its standard input and output directly as the
+connection to a viewer. It never has a listening socket, so cannot accept
+further connections from viewers (it can however connect out to listening
+viewers by use of the vncconfig program). Further viewer connections to the
+same TCP port result in inetd spawning off a new Xvnc to deal with each
+connection. When the connection to the viewer dies, the Xvnc and any
+associated X clients die. This behaviour is most useful when combined with the
+XDMCP options -query and -once. An typical example in inetd.conf might be (all
+on one line):
+
+5950 stream tcp nowait nobody /usr/local/bin/Xvnc Xvnc -inetd -query
+localhost -once securitytypes=none
+
+In this example a viewer connection to :50 will result in a new Xvnc for that
+connection which should display the standard XDM login screen on that machine.
+Because the user needs to login via XDM, it is usually OK to accept connections
+without a VNC password in this case.
+
+In the wait mode, when the first connection comes in, inetd gives the listening
+socket to Xvnc. This means that for a given TCP port, there is only ever one
+Xvnc at a time. Further viewer connections to the same port are accepted by
+the same Xvnc in the normal way. Even when the original connection is broken,
+the Xvnc will continue to run. If this is used with the XDMCP options -query
+and -once, the Xvnc and associated X clients will die when the user logs out of
+the X session in the normal way. It is important to use a VNC password in this
+case. A typical entry in inetd.conf might be:
+
+5951 stream tcp wait james /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd
+
+In fact typically, you would have one entry for each user who uses VNC
+regularly, each of whom has their own dedicated TCP port which they use. In
+this example, when user "james" connects to :51, he enters his VNC password,
+then gets the XDM login screen where he logs in in the normal way. However,
+unlike the previous example, if he disconnects, the session remains persistent,
+and when he reconnects he will get the same session back again. When he logs
+out of the X session, the Xvnc will die, but of course a new one will be
+created automatically the next time he connects.
+
+.SH SEE ALSO
+.BR vncconfig (1),
+.BR vncpasswd (1),
+.BR vncserver (1),
+.BR vncviewer (1),
+.BR Xserver (1),
+.BR inetd (1)
+.br
+http://www.tightvnc.com
+
+.SH AUTHOR
+Tristan Richardson, RealVNC Ltd.
+
+VNC was originally developed by the RealVNC team while at Olivetti
+Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
+implemented by Constantin Kaplinsky. Many other people participated in
+development, testing and support.
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+char buildtime[] = __DATE__ " " __TIME__;
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+
+#include <stdio.h>
+
+extern "C" {
+#define class c_class
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#include "selection.h"
+#define _VNCEXT_SERVER_
+#define _VNCEXT_PROTO_
+#include "vncExt.h"
+#undef class
+#undef xalloc
+}
+
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+#include <rfb/util.h>
+#include <rfb/ServerCore.h>
+#include <rfb/SSecurityFactoryStandard.h>
+#include <rdr/HexOutStream.h>
+#include <rfb/LogWriter.h>
+#undef max
+#undef min
+#include <network/TcpSocket.h>
+
+#include "XserverDesktop.h"
+#include "vncHooks.h"
+#include "vncExtInit.h"
+
+extern "C" {
+
+ extern void vncExtensionInit();
+ static void vncResetProc(ExtensionEntry* extEntry);
+ static void vncBlockHandler(pointer data, OSTimePtr t, pointer readmask);
+ static void vncWakeupHandler(pointer data, int nfds, pointer readmask);
+ static void vncClientStateChange(CallbackListPtr*, pointer, pointer);
+ static void SendSelectionChangeEvent(Atom selection);
+ static int ProcVncExtDispatch(ClientPtr client);
+ static int SProcVncExtDispatch(ClientPtr client);
+
+ extern char *display;
+
+ extern Selection *CurrentSelections;
+ extern int NumCurrentSelections;
+}
+
+using namespace rfb;
+
+static rfb::LogWriter vlog("vncext");
+
+static unsigned long vncExtGeneration = 0;
+static bool initialised = false;
+static XserverDesktop* desktop[MAXSCREENS] = { 0, };
+void* vncFbptr[MAXSCREENS] = { 0, };
+
+static char* clientCutText = 0;
+static int clientCutTextLen = 0;
+
+static XserverDesktop* queryConnectDesktop = 0;
+static void* queryConnectId = 0;
+static int queryConnectTimeout = 0;
+static OsTimerPtr queryConnectTimer = 0;
+
+static struct VncInputSelect* vncInputSelectHead = 0;
+struct VncInputSelect {
+ VncInputSelect(ClientPtr c, Window w, int m) : client(c), window(w), mask(m)
+ {
+ next = vncInputSelectHead;
+ vncInputSelectHead = this;
+ }
+ ClientPtr client;
+ Window window;
+ int mask;
+ VncInputSelect* next;
+};
+
+static int nPrevSelections = 0;
+static TimeStamp* prevSelectionTimes = 0;
+
+static int vncErrorBase = 0;
+static int vncEventBase = 0;
+static char* vncPasswdFile = 0;
+int vncInetdSock = -1;
+
+rfb::AliasParameter rfbauth("rfbauth", "Alias for PasswordFile",
+ &SSecurityFactoryStandard::vncAuthPasswdFile);
+rfb::StringParameter httpDir("httpd",
+ "Directory containing files to serve via HTTP",
+ "");
+rfb::IntParameter httpPort("httpPort", "TCP port to listen for HTTP",0);
+rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
+ &rfb::Server::clientWaitTimeMillis);
+rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
+rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
+rfb::BoolParameter localhostOnly("localhost",
+ "Only allow connections from localhost",
+ false);
+
+void vncExtensionInit()
+{
+ if (vncExtGeneration == serverGeneration) {
+ vlog.error("vncExtensionInit: called twice in same generation?");
+ return;
+ }
+ vncExtGeneration = serverGeneration;
+
+ ExtensionEntry* extEntry
+ = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,
+ ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,
+ StandardMinorOpcode);
+ if (!extEntry) {
+ ErrorF("vncExtInit: AddExtension failed\n");
+ return;
+ }
+
+ vncErrorBase = extEntry->errorBase;
+ vncEventBase = extEntry->eventBase;
+
+ vlog.info("VNC extension running!");
+
+ if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
+ FatalError("AddCallback failed\n");
+ }
+
+ try {
+ if (!initialised) {
+ rfb::initStdIOLoggers();
+ initialised = true;
+ }
+
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+
+ if (!desktop[scr]) {
+ network::TcpListener* listener = 0;
+ network::TcpListener* httpListener = 0;
+ if (scr == 0 && vncInetdSock != -1) {
+ if (network::TcpSocket::isSocket(vncInetdSock) &&
+ !network::TcpSocket::isConnected(vncInetdSock))
+ {
+ listener = new network::TcpListener(0, 0, vncInetdSock, true);
+ vlog.info("inetd wait");
+ }
+ } else {
+ int port = rfbport;
+ if (port == 0) port = 5900 + atoi(display);
+ port += 1000 * scr;
+ listener = new network::TcpListener(port, localhostOnly);
+ vlog.info("Listening for VNC connections on port %d",port);
+ CharArray httpDirStr(httpDir.getData());
+ if (httpDirStr.buf[0]) {
+ port = httpPort;
+ if (port == 0) port = 5800 + atoi(display);
+ port += 1000 * scr;
+ httpListener = new network::TcpListener(port, localhostOnly);
+ vlog.info("Listening for HTTP connections on port %d",port);
+ }
+ }
+
+ CharArray desktopNameStr(desktopName.getData());
+ desktop[scr] = new XserverDesktop(screenInfo.screens[scr], listener,
+ httpListener,
+ desktopNameStr.buf,
+ vncFbptr[scr]);
+ vlog.info("created VNC server for screen %d", scr);
+
+ if (scr == 0 && vncInetdSock != -1 && !listener) {
+ network::Socket* sock = new network::TcpSocket(vncInetdSock);
+ desktop[scr]->addClient(sock, false);
+ vlog.info("added inetd sock");
+ }
+
+ } else {
+ desktop[scr]->serverReset(screenInfo.screens[scr]);
+ }
+
+ vncHooksInit(screenInfo.screens[scr], desktop[scr]);
+ }
+
+ RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0);
+
+ } catch (rdr::Exception& e) {
+ vlog.error("vncExtInit: %s",e.str());
+ }
+}
+
+static void vncResetProc(ExtensionEntry* extEntry)
+{
+}
+
+//
+// vncBlockHandler - called just before the X server goes into select(). Call
+// on to the block handler for each desktop. Then check whether any of the
+// selections have changed, and if so, notify any interested X clients.
+//
+
+static void vncBlockHandler(pointer data, OSTimePtr timeout, pointer readmask)
+{
+ fd_set* fds = (fd_set*)readmask;
+
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ if (desktop[scr]) {
+ desktop[scr]->blockHandler(fds);
+ }
+ }
+
+ if (nPrevSelections != NumCurrentSelections) {
+ prevSelectionTimes
+ = (TimeStamp*)xnfrealloc(prevSelectionTimes,
+ NumCurrentSelections * sizeof(TimeStamp));
+ for (int i = nPrevSelections; i < NumCurrentSelections; i++) {
+ prevSelectionTimes[i].months = 0;
+ prevSelectionTimes[i].milliseconds = 0;
+ }
+ nPrevSelections = NumCurrentSelections;
+ }
+ for (int i = 0; i < NumCurrentSelections; i++) {
+ if (CurrentSelections[i].lastTimeChanged.months
+ != prevSelectionTimes[i].months ||
+ CurrentSelections[i].lastTimeChanged.milliseconds
+ != prevSelectionTimes[i].milliseconds)
+ {
+ SendSelectionChangeEvent(CurrentSelections[i].selection);
+ prevSelectionTimes[i] = CurrentSelections[i].lastTimeChanged;
+ }
+ }
+}
+
+static void vncWakeupHandler(pointer data, int nfds, pointer readmask)
+{
+ fd_set* fds = (fd_set*)readmask;
+
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ if (desktop[scr]) {
+ desktop[scr]->wakeupHandler(fds, nfds);
+ }
+ }
+}
+
+static void vncClientStateChange(CallbackListPtr*, pointer, pointer p)
+{
+ ClientPtr client = ((NewClientInfoRec*)p)->client;
+ if (client->clientState == ClientStateGone) {
+ VncInputSelect** nextPtr = &vncInputSelectHead;
+ for (VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {
+ if (cur->client == client) {
+ *nextPtr = cur->next;
+ delete cur;
+ continue;
+ }
+ nextPtr = &cur->next;
+ }
+ }
+}
+
+void vncBell()
+{
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ if (desktop[scr]) {
+ desktop[scr]->bell();
+ }
+ }
+}
+
+void vncClientGone(int fd)
+{
+ if (fd == vncInetdSock) {
+ fprintf(stderr,"inetdSock client gone\n");
+ GiveUp(0);
+ }
+}
+
+void vncClientCutText(const char* str, int len)
+{
+ delete [] clientCutText;
+ clientCutText = new char[len];
+ memcpy(clientCutText, str, len);
+ clientCutTextLen = len;
+ xVncExtClientCutTextNotifyEvent ev;
+ ev.type = vncEventBase + VncExtClientCutTextNotify;
+ for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+ if (cur->mask & VncExtClientCutTextMask) {
+ ev.sequenceNumber = cur->client->sequence;
+ ev.window = cur->window;
+ ev.time = GetTimeInMillis();
+ if (cur->client->swapped) {
+ int n;
+ swaps(&ev.sequenceNumber, n);
+ swapl(&ev.window, n);
+ swapl(&ev.time, n);
+ }
+ WriteToClient(cur->client, sizeof(xVncExtClientCutTextNotifyEvent),
+ (char *)&ev);
+ }
+ }
+}
+
+
+static CARD32 queryConnectTimerCallback(OsTimerPtr timer,
+ CARD32 now, pointer arg)
+{
+ if (queryConnectTimeout)
+ queryConnectDesktop->approveConnection(queryConnectId, false, "The attempt to prompt the user to accept the connection failed");
+ // Re-notify clients, causing them to discover that we're done
+ vncQueryConnect(queryConnectDesktop, queryConnectId);
+ return 0;
+}
+
+void vncQueryConnect(XserverDesktop* desktop, void* opaqueId)
+{
+ // Only one query can be processed at any one time
+ if (queryConnectTimeout && ((desktop != queryConnectDesktop) ||
+ (opaqueId != queryConnectId))) {
+ desktop->approveConnection(opaqueId, false,
+ "Another connection is currently being queried.");
+ return;
+ }
+
+ // Get the query timeout. If it's zero, there is no query.
+ queryConnectTimeout = desktop->getQueryTimeout(opaqueId);
+ queryConnectId = queryConnectTimeout ? opaqueId : 0;
+ queryConnectDesktop = queryConnectTimeout ? desktop : 0;
+
+ // Notify clients
+ bool notified = false;
+ xVncExtQueryConnectNotifyEvent ev;
+ ev.type = vncEventBase + VncExtQueryConnectNotify;
+ for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+ if (cur->mask & VncExtQueryConnectMask) {
+ ev.sequenceNumber = cur->client->sequence;
+ ev.window = cur->window;
+ if (cur->client->swapped) {
+ int n;
+ swaps(&ev.sequenceNumber, n);
+ swapl(&ev.window, n);
+ }
+ WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),
+ (char *)&ev);
+ notified = true;
+ }
+ }
+
+ // If we're being asked to query a connection (rather than to cancel
+ // a query), and haven't been able to notify clients then reject it.
+ if (queryConnectTimeout && !notified) {
+ queryConnectTimeout = 0;
+ queryConnectId = 0;
+ queryConnectDesktop = 0;
+ desktop->approveConnection(opaqueId, false,
+ "Unable to query the local user to accept the connection.");
+ return;
+ }
+
+ // Set a timer so that if no-one ever responds, we will eventually
+ // reject the connection
+ // NB: We don't set a timer if sock is null, since that indicates
+ // that pending queries should be cancelled.
+ if (queryConnectDesktop)
+ queryConnectTimer = TimerSet(queryConnectTimer, 0,
+ queryConnectTimeout*2000,
+ queryConnectTimerCallback, 0);
+ else
+ TimerCancel(queryConnectTimer);
+}
+
+static void SendSelectionChangeEvent(Atom selection)
+{
+ xVncExtSelectionChangeNotifyEvent ev;
+ ev.type = vncEventBase + VncExtSelectionChangeNotify;
+ for (VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
+ if (cur->mask & VncExtSelectionChangeMask) {
+ ev.sequenceNumber = cur->client->sequence;
+ ev.window = cur->window;
+ ev.selection = selection;
+ if (cur->client->swapped) {
+ int n;
+ swaps(&ev.sequenceNumber, n);
+ swapl(&ev.window, n);
+ swapl(&ev.selection, n);
+ }
+ WriteToClient(cur->client, sizeof(xVncExtSelectionChangeNotifyEvent),
+ (char *)&ev);
+ }
+ }
+}
+
+static int ProcVncExtSetParam(ClientPtr client)
+{
+ REQUEST(xVncExtSetParamReq);
+ REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen);
+ CharArray param(stuff->paramLen+1);
+ strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+ param.buf[stuff->paramLen] = 0;
+
+ xVncExtSetParamReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.success = rfb::Configuration::setParam(param.buf);
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int SProcVncExtSetParam(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtSetParamReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);
+ return ProcVncExtSetParam(client);
+}
+
+static int ProcVncExtGetParam(ClientPtr client)
+{
+ REQUEST(xVncExtGetParamReq);
+ REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);
+ CharArray param(stuff->paramLen+1);
+ strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+ param.buf[stuff->paramLen] = 0;
+
+ xVncExtGetParamReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.success = 0;
+ int len = 0;
+ char* value = 0;
+ rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
+ // Hack to avoid exposing password!
+ if (strcasecmp(param.buf, "Password") == 0)
+ p = 0;
+ if (p) {
+ value = p->getValueStr();
+ rep.success = 1;
+ len = value ? strlen(value) : 0;
+ }
+ rep.length = (len + 3) >> 2;
+ rep.valueLen = len;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.valueLen, n);
+ }
+ WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);
+ if (value)
+ WriteToClient(client, len, value);
+ delete [] value;
+ return (client->noClientException);
+}
+
+static int SProcVncExtGetParam(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtGetParamReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);
+ return ProcVncExtGetParam(client);
+}
+
+static int ProcVncExtGetParamDesc(ClientPtr client)
+{
+ REQUEST(xVncExtGetParamDescReq);
+ REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);
+ CharArray param(stuff->paramLen+1);
+ strncpy(param.buf, (char*)&stuff[1], stuff->paramLen);
+ param.buf[stuff->paramLen] = 0;
+
+ xVncExtGetParamDescReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.success = 0;
+ int len = 0;
+ const char* desc = 0;
+ rfb::VoidParameter* p = rfb::Configuration::getParam(param.buf);
+ if (p) {
+ desc = p->getDescription();
+ rep.success = 1;
+ len = desc ? strlen(desc) : 0;
+ }
+ rep.length = (len + 3) >> 2;
+ rep.descLen = len;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.descLen, n);
+ }
+ WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);
+ if (desc)
+ WriteToClient(client, len, (char*)desc);
+ return (client->noClientException);
+}
+
+static int SProcVncExtGetParamDesc(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtGetParamDescReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);
+ return ProcVncExtGetParamDesc(client);
+}
+
+static int ProcVncExtListParams(ClientPtr client)
+{
+ REQUEST(xVncExtListParamsReq);
+ REQUEST_SIZE_MATCH(xVncExtListParamsReq);
+
+ xVncExtListParamsReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+
+ int nParams = 0;
+ int len = 0;
+ for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+ int l = strlen(i.param->getName());
+ if (l <= 255) {
+ nParams++;
+ len += l + 1;
+ }
+ }
+ rep.length = (len + 3) >> 2;
+ rep.nParams = nParams;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.nParams, n);
+ }
+ WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);
+ rdr::U8* data = new rdr::U8[len];
+ rdr::U8* ptr = data;
+ for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+ int l = strlen(i.param->getName());
+ if (l <= 255) {
+ *ptr++ = l;
+ memcpy(ptr, i.param->getName(), l);
+ ptr += l;
+ }
+ }
+ WriteToClient(client, len, (char*)data);
+ delete [] data;
+ return (client->noClientException);
+}
+
+static int SProcVncExtListParams(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtListParamsReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncExtListParamsReq);
+ return ProcVncExtListParams(client);
+}
+
+static int ProcVncExtSetServerCutText(ClientPtr client)
+{
+ REQUEST(xVncExtSetServerCutTextReq);
+ REQUEST_FIXED_SIZE(xVncExtSetServerCutTextReq, stuff->textLen);
+ char* str = new char[stuff->textLen+1];
+ strncpy(str, (char*)&stuff[1], stuff->textLen);
+ str[stuff->textLen] = 0;
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ if (desktop[scr]) {
+ desktop[scr]->serverCutText(str, stuff->textLen);
+ }
+ }
+ delete [] str;
+ return (client->noClientException);
+}
+
+static int SProcVncExtSetServerCutText(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtSetServerCutTextReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xVncExtSetServerCutTextReq);
+ swapl(&stuff->textLen, n);
+ return ProcVncExtSetServerCutText(client);
+}
+
+static int ProcVncExtGetClientCutText(ClientPtr client)
+{
+ REQUEST(xVncExtGetClientCutTextReq);
+ REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
+
+ xVncExtGetClientCutTextReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.length = (clientCutTextLen + 3) >> 2;
+ rep.sequenceNumber = client->sequence;
+ rep.textLen = clientCutTextLen;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.textLen, n);
+ }
+ WriteToClient(client, sizeof(xVncExtGetClientCutTextReply), (char *)&rep);
+ if (clientCutText)
+ WriteToClient(client, clientCutTextLen, clientCutText);
+ return (client->noClientException);
+}
+
+static int SProcVncExtGetClientCutText(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtGetClientCutTextReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncExtGetClientCutTextReq);
+ return ProcVncExtGetClientCutText(client);
+}
+
+static int ProcVncExtSelectInput(ClientPtr client)
+{
+ REQUEST(xVncExtSelectInputReq);
+ REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
+ VncInputSelect** nextPtr = &vncInputSelectHead;
+ VncInputSelect* cur;
+ for (cur = vncInputSelectHead; cur; cur = *nextPtr) {
+ if (cur->client == client && cur->window == stuff->window) {
+ cur->mask = stuff->mask;
+ if (!cur->mask) {
+ *nextPtr = cur->next;
+ delete cur;
+ }
+ break;
+ }
+ nextPtr = &cur->next;
+ }
+ if (!cur) {
+ cur = new VncInputSelect(client, stuff->window, stuff->mask);
+ }
+ return (client->noClientException);
+}
+
+static int SProcVncExtSelectInput(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtSelectInputReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->mask, n);
+ return ProcVncExtSelectInput(client);
+}
+
+static int ProcVncExtConnect(ClientPtr client)
+{
+ REQUEST(xVncExtConnectReq);
+ REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);
+ CharArray str(stuff->strLen+1);
+ strncpy(str.buf, (char*)&stuff[1], stuff->strLen);
+ str.buf[stuff->strLen] = 0;
+
+ xVncExtConnectReply rep;
+ rep.success = 0;
+ if (desktop[0]) {
+ if (stuff->strLen == 0) {
+ try {
+ desktop[0]->disconnectClients();
+ rep.success = 1;
+ } catch (rdr::Exception& e) {
+ vlog.error("Disconnecting all clients: %s",e.str());
+ }
+ } else {
+ int port = 5500;
+ for (int i = 0; i < stuff->strLen; i++) {
+ if (str.buf[i] == ':') {
+ port = atoi(&str.buf[i+1]);
+ str.buf[i] = 0;
+ break;
+ }
+ }
+
+ try {
+ network::Socket* sock = new network::TcpSocket(str.buf, port);
+ desktop[0]->addClient(sock, true);
+ rep.success = 1;
+ } catch (rdr::Exception& e) {
+ vlog.error("Reverse connection: %s",e.str());
+ }
+ }
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (client->swapped) {
+ int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int SProcVncExtConnect(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtConnectReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);
+ return ProcVncExtConnect(client);
+}
+
+
+static int ProcVncExtGetQueryConnect(ClientPtr client)
+{
+ REQUEST(xVncExtGetQueryConnectReq);
+ REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
+
+ const char *qcAddress=0, *qcUsername=0;
+ int qcTimeout;
+ if (queryConnectDesktop)
+ qcTimeout = queryConnectDesktop->getQueryTimeout(queryConnectId,
+ &qcAddress, &qcUsername);
+ else
+ qcTimeout = 0;
+
+ xVncExtGetQueryConnectReply rep;
+ int n;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.timeout = qcTimeout;
+ rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;
+ rep.userLen = qcTimeout ? strlen(qcUsername) : 0;
+ rep.opaqueId = (CARD32)queryConnectId;
+ rep.length = (rep.userLen + rep.addrLen + 3) >> 2;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.userLen, n);
+ swapl(&rep.addrLen, n);
+ swapl(&rep.timeout, n);
+ swapl(&rep.opaqueId, n);
+ }
+ WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);
+ if (qcTimeout)
+ WriteToClient(client, strlen(qcAddress), (char*)qcAddress);
+ if (qcTimeout)
+ WriteToClient(client, strlen(qcUsername), (char*)qcUsername);
+ return (client->noClientException);
+}
+
+static int SProcVncExtGetQueryConnect(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtGetQueryConnectReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
+ return ProcVncExtGetQueryConnect(client);
+}
+
+
+static int ProcVncExtApproveConnect(ClientPtr client)
+{
+ REQUEST(xVncExtApproveConnectReq);
+ REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
+ if (queryConnectId == (void*)stuff->opaqueId) {
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ if (desktop[scr]) {
+ desktop[scr]->approveConnection(queryConnectId, stuff->approve,
+ "Connection rejected by local user");
+ }
+ }
+ // Inform other clients of the event and tidy up
+ vncQueryConnect(queryConnectDesktop, queryConnectId);
+ }
+ return (client->noClientException);
+}
+
+static int SProcVncExtApproveConnect(ClientPtr client)
+{
+ register char n;
+ REQUEST(xVncExtApproveConnectReq);
+ swaps(&stuff->length, n);
+ swapl(&stuff->opaqueId, n);
+ REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
+ return ProcVncExtApproveConnect(client);
+}
+
+
+static int ProcVncExtDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_VncExtSetParam:
+ return ProcVncExtSetParam(client);
+ case X_VncExtGetParam:
+ return ProcVncExtGetParam(client);
+ case X_VncExtGetParamDesc:
+ return ProcVncExtGetParamDesc(client);
+ case X_VncExtListParams:
+ return ProcVncExtListParams(client);
+ case X_VncExtSetServerCutText:
+ return ProcVncExtSetServerCutText(client);
+ case X_VncExtGetClientCutText:
+ return ProcVncExtGetClientCutText(client);
+ case X_VncExtSelectInput:
+ return ProcVncExtSelectInput(client);
+ case X_VncExtConnect:
+ return ProcVncExtConnect(client);
+ case X_VncExtGetQueryConnect:
+ return ProcVncExtGetQueryConnect(client);
+ case X_VncExtApproveConnect:
+ return ProcVncExtApproveConnect(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int SProcVncExtDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_VncExtSetParam:
+ return SProcVncExtSetParam(client);
+ case X_VncExtGetParam:
+ return SProcVncExtGetParam(client);
+ case X_VncExtGetParamDesc:
+ return SProcVncExtGetParamDesc(client);
+ case X_VncExtListParams:
+ return SProcVncExtListParams(client);
+ case X_VncExtSetServerCutText:
+ return SProcVncExtSetServerCutText(client);
+ case X_VncExtGetClientCutText:
+ return SProcVncExtGetClientCutText(client);
+ case X_VncExtSelectInput:
+ return SProcVncExtSelectInput(client);
+ case X_VncExtConnect:
+ return SProcVncExtConnect(client);
+ case X_VncExtGetQueryConnect:
+ return SProcVncExtGetQueryConnect(client);
+ case X_VncExtApproveConnect:
+ return SProcVncExtApproveConnect(client);
+ default:
+ return BadRequest;
+ }
+}
+
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __VNCEXTINIT_H__
+#define __VNCEXTINIT_H__
+
+#include <rfb/Configuration.h>
+#include "XserverDesktop.h"
+
+extern void vncClientCutText(const char* str, int len);
+extern void vncQueryConnect(XserverDesktop* desktop, void* opaqueId);
+extern void vncClientGone(int fd);
+extern void vncBell();
+extern void* vncFbptr[];
+extern int vncInetdSock;
+extern rfb::StringParameter httpDir;
+
+#endif
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+
+#include <stdio.h>
+#include "XserverDesktop.h"
+#include "vncHooks.h"
+
+extern "C" {
+#define class c_class
+#define private c_private
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "gcstruct.h"
+#include "regionstr.h"
+#include "dixfontstr.h"
+#include "colormapst.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+
+#ifdef GC_HAS_COMPOSITE_CLIP
+#define COMPOSITE_CLIP(gc) ((gc)->pCompositeClip)
+#else
+#include "mfb.h"
+#define COMPOSITE_CLIP(gc) \
+ (((mfbPrivGCPtr)((gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
+#endif
+
+#undef class
+#undef private
+}
+
+#include "RegionHelper.h"
+
+#define DBGPRINT(x) //(fprintf x)
+
+// MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
+// operations like Polylines and PolySegment. If the operation is more complex
+// than this, we simply use the bounding box. Ideally it would be a
+// command-line option, but that would involve an extra malloc each time, so we
+// fix it here.
+#define MAX_RECTS_PER_OP 5
+
+static unsigned long vncHooksGeneration = 0;
+
+// vncHooksScreenRec and vncHooksGCRec contain pointers to the original
+// functions which we "wrap" in order to hook the screen changes. The screen
+// functions are each wrapped individually, while the GC "funcs" and "ops" are
+// wrapped as a unit.
+
+typedef struct {
+ XserverDesktop* desktop;
+
+ CloseScreenProcPtr CloseScreen;
+ CreateGCProcPtr CreateGC;
+ PaintWindowBackgroundProcPtr PaintWindowBackground;
+ PaintWindowBorderProcPtr PaintWindowBorder;
+ CopyWindowProcPtr CopyWindow;
+ ClearToBackgroundProcPtr ClearToBackground;
+ RestoreAreasProcPtr RestoreAreas;
+ InstallColormapProcPtr InstallColormap;
+ StoreColorsProcPtr StoreColors;
+ DisplayCursorProcPtr DisplayCursor;
+ ScreenBlockHandlerProcPtr BlockHandler;
+#ifdef RENDER
+ CompositeProcPtr Composite;
+#endif
+} vncHooksScreenRec, *vncHooksScreenPtr;
+
+typedef struct {
+ GCFuncs *wrappedFuncs;
+ GCOps *wrappedOps;
+} vncHooksGCRec, *vncHooksGCPtr;
+
+static int vncHooksScreenIndex;
+static int vncHooksGCIndex;
+
+
+// screen functions
+
+static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen);
+static Bool vncHooksCreateGC(GCPtr pGC);
+static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+ int what);
+static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr pOldRegion);
+static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
+ int h, Bool generateExposures);
+static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
+static void vncHooksInstallColormap(ColormapPtr pColormap);
+static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
+ xColorItem* pdef);
+static Bool vncHooksDisplayCursor(ScreenPtr pScreen, CursorPtr cursor);
+static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask);
+#ifdef RENDER
+static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask,
+ PicturePtr pDst, INT16 xSrc, INT16 ySrc, INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+#endif
+
+// GC "funcs"
+
+static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable);
+static void vncHooksChangeGC(GCPtr pGC, unsigned long mask);
+static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst);
+static void vncHooksDestroyGC(GCPtr pGC);
+static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue,int nrects);
+static void vncHooksDestroyClip(GCPtr pGC);
+static void vncHooksCopyClip(GCPtr dst, GCPtr src);
+
+static GCFuncs vncHooksGCFuncs = {
+ vncHooksValidateGC, vncHooksChangeGC, vncHooksCopyGC, vncHooksDestroyGC,
+ vncHooksChangeClip, vncHooksDestroyClip, vncHooksCopyClip,
+};
+
+// GC "ops"
+
+static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int fSorted);
+static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans,
+ int fSorted);
+static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad,
+ int format, char *pBits);
+static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w, int h,
+ int dstx, int dsty);
+static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long plane);
+static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, xPoint *pts);
+static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr ppts);
+static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
+ xSegment *segs);
+static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle *rects);
+static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+ xArc *arcs);
+static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int count, DDXPointPtr pts);
+static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle *rects);
+static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+ xArc *arcs);
+static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, char *chars);
+static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, char *chars);
+static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase);
+static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
+ DrawablePtr pDrawable, int w, int h, int x,
+ int y);
+
+static GCOps vncHooksGCOps = {
+ vncHooksFillSpans, vncHooksSetSpans, vncHooksPutImage, vncHooksCopyArea,
+ vncHooksCopyPlane, vncHooksPolyPoint, vncHooksPolylines, vncHooksPolySegment,
+ vncHooksPolyRectangle, vncHooksPolyArc, vncHooksFillPolygon,
+ vncHooksPolyFillRect, vncHooksPolyFillArc, vncHooksPolyText8,
+ vncHooksPolyText16, vncHooksImageText8, vncHooksImageText16,
+ vncHooksImageGlyphBlt, vncHooksPolyGlyphBlt, vncHooksPushPixels
+};
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// vncHooksInit() is called at initialisation time and every time the server
+// resets. It is called once for each screen, but the indexes are only
+// allocated once for each server generation.
+
+Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop)
+{
+ vncHooksScreenPtr vncHooksScreen;
+
+ if (vncHooksGeneration != serverGeneration) {
+ vncHooksGeneration = serverGeneration;
+
+ vncHooksScreenIndex = AllocateScreenPrivateIndex();
+ if (vncHooksScreenIndex < 0) {
+ ErrorF("vncHooksInit: AllocateScreenPrivateIndex failed\n");
+ return FALSE;
+ }
+
+ vncHooksGCIndex = AllocateGCPrivateIndex();
+ if (vncHooksGCIndex < 0) {
+ ErrorF("vncHooksInit: AllocateGCPrivateIndex failed\n");
+ return FALSE;
+ }
+ }
+
+ if (!AllocateGCPrivate(pScreen, vncHooksGCIndex, sizeof(vncHooksGCRec))) {
+ ErrorF("vncHooksInit: AllocateGCPrivate failed\n");
+ return FALSE;
+ }
+
+ vncHooksScreen = (vncHooksScreenPtr)xnfalloc(sizeof(vncHooksScreenRec));
+ pScreen->devPrivates[vncHooksScreenIndex].ptr = (pointer)vncHooksScreen;
+
+ vncHooksScreen->desktop = desktop;
+
+ vncHooksScreen->CloseScreen = pScreen->CloseScreen;
+ vncHooksScreen->CreateGC = pScreen->CreateGC;
+ vncHooksScreen->PaintWindowBackground = pScreen->PaintWindowBackground;
+ vncHooksScreen->PaintWindowBorder = pScreen->PaintWindowBorder;
+ vncHooksScreen->CopyWindow = pScreen->CopyWindow;
+ vncHooksScreen->ClearToBackground = pScreen->ClearToBackground;
+ vncHooksScreen->RestoreAreas = pScreen->RestoreAreas;
+ vncHooksScreen->InstallColormap = pScreen->InstallColormap;
+ vncHooksScreen->StoreColors = pScreen->StoreColors;
+ vncHooksScreen->DisplayCursor = pScreen->DisplayCursor;
+ vncHooksScreen->BlockHandler = pScreen->BlockHandler;
+#ifdef RENDER
+ PictureScreenPtr ps;
+ ps = GetPictureScreenIfSet(pScreen);
+ if (ps) {
+ vncHooksScreen->Composite = ps->Composite;
+ }
+#endif
+
+ pScreen->CloseScreen = vncHooksCloseScreen;
+ pScreen->CreateGC = vncHooksCreateGC;
+ pScreen->PaintWindowBackground = vncHooksPaintWindowBackground;
+ pScreen->PaintWindowBorder = vncHooksPaintWindowBorder;
+ pScreen->CopyWindow = vncHooksCopyWindow;
+ pScreen->ClearToBackground = vncHooksClearToBackground;
+ pScreen->RestoreAreas = vncHooksRestoreAreas;
+ pScreen->InstallColormap = vncHooksInstallColormap;
+ pScreen->StoreColors = vncHooksStoreColors;
+ pScreen->DisplayCursor = vncHooksDisplayCursor;
+ pScreen->BlockHandler = vncHooksBlockHandler;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = vncHooksComposite;
+ }
+#endif
+
+ return TRUE;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// screen functions
+//
+
+// SCREEN_UNWRAP and SCREEN_REWRAP unwrap and rewrap the given screen function.
+// It would be nice to do this with a C++ class, but each function is of a
+// distinct type, so it would have to use templates, and it's not worth that
+// much pain.
+
+#define SCREEN_UNWRAP(scrn,field) \
+ ScreenPtr pScreen = scrn; \
+ vncHooksScreenPtr vncHooksScreen \
+ = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
+ pScreen->field = vncHooksScreen->field; \
+ DBGPRINT((stderr,"vncHooks" #field " called\n"));
+
+#define SCREEN_REWRAP(field) pScreen->field = vncHooks##field;
+
+
+// CloseScreen - unwrap the screen functions and call the original CloseScreen
+// function
+
+static Bool vncHooksCloseScreen(int i, ScreenPtr pScreen_)
+{
+ SCREEN_UNWRAP(pScreen_, CloseScreen);
+
+ pScreen->CreateGC = vncHooksScreen->CreateGC;
+ pScreen->PaintWindowBackground = vncHooksScreen->PaintWindowBackground;
+ pScreen->PaintWindowBorder = vncHooksScreen->PaintWindowBorder;
+ pScreen->CopyWindow = vncHooksScreen->CopyWindow;
+ pScreen->ClearToBackground = vncHooksScreen->ClearToBackground;
+ pScreen->RestoreAreas = vncHooksScreen->RestoreAreas;
+ pScreen->InstallColormap = vncHooksScreen->InstallColormap;
+ pScreen->StoreColors = vncHooksScreen->StoreColors;
+ pScreen->DisplayCursor = vncHooksScreen->DisplayCursor;
+ pScreen->BlockHandler = vncHooksScreen->BlockHandler;
+
+ xfree((pointer)vncHooksScreen);
+
+ DBGPRINT((stderr,"vncHooksCloseScreen: unwrapped screen functions\n"));
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
+
+// CreateGC - wrap the "GC funcs"
+
+static Bool vncHooksCreateGC(GCPtr pGC)
+{
+ SCREEN_UNWRAP(pGC->pScreen, CreateGC);
+
+ vncHooksGCPtr vncHooksGC
+ = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+
+ Bool ret = (*pScreen->CreateGC) (pGC);
+
+ vncHooksGC->wrappedOps = 0;
+ vncHooksGC->wrappedFuncs = pGC->funcs;
+ pGC->funcs = &vncHooksGCFuncs;
+
+ SCREEN_REWRAP(CreateGC);
+
+ return ret;
+}
+
+// PaintWindowBackground - changed region is the given region
+
+static void vncHooksPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion,
+ int what)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBackground);
+
+ RegionHelper changed(pScreen, pRegion);
+
+ (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ SCREEN_REWRAP(PaintWindowBackground);
+}
+
+// PaintWindowBorder - changed region is the given region
+
+static void vncHooksPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion,
+ int what)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder);
+
+ RegionHelper changed(pScreen, pRegion);
+
+ (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ SCREEN_REWRAP(PaintWindowBorder);
+}
+
+// CopyWindow - destination of the copy is the old region, clipped by
+// borderClip, translated by the delta. This call only does the copy - it
+// doesn't affect any other bits.
+
+static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr pOldRegion)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, CopyWindow);
+
+ RegionHelper copied(pScreen, pOldRegion);
+ int dx = pWin->drawable.x - ptOldOrg.x;
+ int dy = pWin->drawable.y - ptOldOrg.y;
+ REGION_TRANSLATE(pScreen, copied.reg, dx, dy);
+ REGION_INTERSECT(pWin->drawable.pScreen, copied.reg, copied.reg,
+ &pWin->borderClip);
+
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
+
+ vncHooksScreen->desktop->add_copied(copied.reg, dx, dy);
+
+ SCREEN_REWRAP(CopyWindow);
+}
+
+// ClearToBackground - changed region is the given rectangle, clipped by
+// clipList, but only if generateExposures is false.
+
+static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w,
+ int h, Bool generateExposures)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, ClearToBackground);
+
+ BoxRec box;
+ 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);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, &pWin->clipList);
+
+ (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
+
+ if (!generateExposures) {
+ vncHooksScreen->desktop->add_changed(changed.reg);
+ }
+
+ SCREEN_REWRAP(ClearToBackground);
+}
+
+// RestoreAreas - changed region is the given region
+
+static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion)
+{
+ SCREEN_UNWRAP(pWin->drawable.pScreen, RestoreAreas);
+
+ RegionHelper changed(pScreen, pRegion);
+
+ RegionPtr result = (*pScreen->RestoreAreas) (pWin, pRegion);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ SCREEN_REWRAP(RestoreAreas);
+
+ return result;
+}
+
+// InstallColormap - get the new colormap
+
+static void vncHooksInstallColormap(ColormapPtr pColormap)
+{
+ SCREEN_UNWRAP(pColormap->pScreen, InstallColormap);
+
+ (*pScreen->InstallColormap) (pColormap);
+
+ vncHooksScreen->desktop->setColormap(pColormap);
+
+ SCREEN_REWRAP(InstallColormap);
+}
+
+// StoreColors - get the colormap changes
+
+static void vncHooksStoreColors(ColormapPtr pColormap, int ndef,
+ xColorItem* pdef)
+{
+ SCREEN_UNWRAP(pColormap->pScreen, StoreColors);
+
+ (*pScreen->StoreColors) (pColormap, ndef, pdef);
+
+ vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef);
+
+ SCREEN_REWRAP(StoreColors);
+}
+
+// DisplayCursor - get the cursor shape
+
+static Bool vncHooksDisplayCursor(ScreenPtr pScreen_, CursorPtr cursor)
+{
+ SCREEN_UNWRAP(pScreen_, DisplayCursor);
+
+ Bool ret = (*pScreen->DisplayCursor) (pScreen, cursor);
+
+ vncHooksScreen->desktop->setCursor(cursor);
+
+ SCREEN_REWRAP(DisplayCursor);
+
+ return ret;
+}
+
+// BlockHandler - ignore any changes during the block handler - it's likely
+// these are just drawing the cursor.
+
+static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
+ pointer pReadmask)
+{
+ SCREEN_UNWRAP(screenInfo.screens[i], BlockHandler);
+
+ vncHooksScreen->desktop->ignoreHooks(true);
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ vncHooksScreen->desktop->ignoreHooks(false);
+
+ SCREEN_REWRAP(BlockHandler);
+}
+
+// Composite - needed for RENDER
+
+#ifdef RENDER
+void vncHooksComposite(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;
+ vncHooksScreenPtr vncHooksScreen = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr);
+ BoxRec box;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ rfb::Rect rect1, rect2;
+
+ rect1.setXYWH(pDst->pDrawable->x + xDst,
+ pDst->pDrawable->y + yDst,
+ width,
+ height);
+
+ rect2 = rect1.intersect(vncHooksScreen->desktop->getRect());
+ if (!rect2.is_empty()) {
+ box.x1 = rect2.tl.x;
+ box.y1 = rect2.tl.y;
+ box.x2 = rect2.br.x;
+ box.y2 = rect2.br.y;
+ RegionHelper changed(pScreen, &box, 0);
+ vncHooksScreen->desktop->add_changed(changed.reg);
+ }
+
+ ps->Composite = vncHooksScreen->Composite;
+ (*ps->Composite)(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+ ps->Composite = vncHooksComposite;
+}
+
+#endif /* RENDER */
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GC "funcs"
+//
+
+// GCFuncUnwrapper is a helper class which unwraps the GC funcs and ops in its
+// constructor and rewraps them in its destructor.
+
+class GCFuncUnwrapper {
+public:
+ GCFuncUnwrapper(GCPtr pGC_) : pGC(pGC_) {
+ vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+ pGC->funcs = vncHooksGC->wrappedFuncs;
+ if (vncHooksGC->wrappedOps)
+ pGC->ops = vncHooksGC->wrappedOps;
+ }
+ ~GCFuncUnwrapper() {
+ vncHooksGC->wrappedFuncs = pGC->funcs;
+ pGC->funcs = &vncHooksGCFuncs;
+ if (vncHooksGC->wrappedOps) {
+ vncHooksGC->wrappedOps = pGC->ops;
+ pGC->ops = &vncHooksGCOps;
+ }
+ }
+ GCPtr pGC;
+ vncHooksGCPtr vncHooksGC;
+};
+
+
+// ValidateGC - wrap the "ops" if a viewable window
+
+static void vncHooksValidateGC(GCPtr pGC, unsigned long changes,
+ DrawablePtr pDrawable)
+{
+ GCFuncUnwrapper u(pGC);
+
+ DBGPRINT((stderr,"vncHooksValidateGC called\n"));
+
+ (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
+
+ u.vncHooksGC->wrappedOps = 0;
+ 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)) {
+ u.vncHooksGC->wrappedOps = pGC->ops;
+ DBGPRINT((stderr,"vncHooksValidateGC: wrapped GC ops\n"));
+ }
+ }
+}
+
+// Other GC funcs - just unwrap and call on
+
+static void vncHooksChangeGC(GCPtr pGC, unsigned long mask) {
+ GCFuncUnwrapper u(pGC);
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+}
+static void vncHooksCopyGC(GCPtr src, unsigned long mask, GCPtr dst) {
+ GCFuncUnwrapper u(dst);
+ (*dst->funcs->CopyGC) (src, mask, dst);
+}
+static void vncHooksDestroyGC(GCPtr pGC) {
+ GCFuncUnwrapper u(pGC);
+ (*pGC->funcs->DestroyGC) (pGC);
+}
+static void vncHooksChangeClip(GCPtr pGC, int type, pointer pValue, int nrects)
+{
+ GCFuncUnwrapper u(pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pValue, nrects);
+}
+static void vncHooksDestroyClip(GCPtr pGC) {
+ GCFuncUnwrapper u(pGC);
+ (*pGC->funcs->DestroyClip) (pGC);
+}
+static void vncHooksCopyClip(GCPtr dst, GCPtr src) {
+ GCFuncUnwrapper u(dst);
+ (*dst->funcs->CopyClip) (dst, src);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GC "ops"
+//
+
+// GCOpUnwrapper is a helper class which unwraps the GC funcs and ops in its
+// constructor and rewraps them in its destructor.
+
+class GCOpUnwrapper {
+public:
+ GCOpUnwrapper(DrawablePtr pDrawable, GCPtr pGC_)
+ : pGC(pGC_), pScreen(pDrawable->pScreen)
+ {
+ vncHooksGC = (vncHooksGCPtr)pGC->devPrivates[vncHooksGCIndex].ptr;
+ oldFuncs = pGC->funcs;
+ pGC->funcs = vncHooksGC->wrappedFuncs;
+ pGC->ops = vncHooksGC->wrappedOps;
+ }
+ ~GCOpUnwrapper() {
+ vncHooksGC->wrappedOps = pGC->ops;
+ pGC->funcs = oldFuncs;
+ pGC->ops = &vncHooksGCOps;
+ }
+ GCPtr pGC;
+ vncHooksGCPtr vncHooksGC;
+ GCFuncs* oldFuncs;
+ ScreenPtr pScreen;
+};
+
+#define GC_OP_UNWRAPPER(pDrawable, pGC, name) \
+ GCOpUnwrapper u(pDrawable, pGC); \
+ ScreenPtr pScreen = (pDrawable)->pScreen; \
+ vncHooksScreenPtr vncHooksScreen \
+ = ((vncHooksScreenPtr)pScreen->devPrivates[vncHooksScreenIndex].ptr); \
+ DBGPRINT((stderr,"vncHooks" #name " called\n"));
+
+
+// FillSpans - changed region is the whole of borderClip. This is pessimistic,
+// but I believe this function is rarely used so it doesn't matter.
+
+static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit,
+ int fSorted)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, FillSpans);
+
+ RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
+
+ (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// SetSpans - changed region is the whole of borderClip. This is pessimistic,
+// but I believe this function is rarely used so it doesn't matter.
+
+static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans,
+ int fSorted)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, SetSpans);
+
+ RegionHelper changed(pScreen, &((WindowPtr)pDrawable)->borderClip);
+
+ (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PutImage - changed region is the given rectangle, clipped by pCompositeClip
+
+static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad,
+ int format, char *pBits)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PutImage);
+
+ BoxRec box;
+ box.x1 = x + pDrawable->x;
+ box.y1 = y + pDrawable->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ pBits);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// CopyArea - destination of the copy is the dest rectangle, clipped by
+// pCompositeClip. Any parts of the destination which cannot be copied from
+// the source (could be all of it) go into the changed region.
+
+static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w, int h,
+ int dstx, int dsty)
+{
+ GC_OP_UNWRAPPER(pDst, pGC, CopyArea);
+
+ BoxRec box;
+ box.x1 = dstx + pDst->x;
+ box.y1 = dsty + pDst->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ RegionHelper dst(pScreen, &box, 0);
+ REGION_INTERSECT(pScreen, dst.reg, dst.reg, COMPOSITE_CLIP(pGC));
+
+ RegionHelper src(pScreen);
+
+ if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pScreen)) {
+ box.x1 = srcx + pSrc->x;
+ box.y1 = srcy + pSrc->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ src.init(&box, 0);
+ REGION_INTERSECT(pScreen, src.reg, src.reg, &((WindowPtr)pSrc)->clipList);
+ REGION_TRANSLATE(pScreen, src.reg,
+ dstx + pDst->x - srcx - pSrc->x,
+ dsty + pDst->y - srcy - pSrc->y);
+ } else {
+ src.init(NullBox, 0);
+ }
+
+ RegionHelper changed(pScreen, NullBox, 0);
+ REGION_SUBTRACT(pScreen, changed.reg, dst.reg, src.reg);
+ REGION_INTERSECT(pScreen, dst.reg, dst.reg, src.reg);
+
+ RegionPtr rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty);
+
+ if (REGION_NOTEMPTY(pScreen, dst.reg))
+ vncHooksScreen->desktop->add_copied(dst.reg,
+ dstx + pDst->x - srcx - pSrc->x,
+ dsty + pDst->y - srcy - pSrc->y);
+
+ if (REGION_NOTEMPTY(pScreen, changed.reg))
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ return rgn;
+}
+
+
+// CopyPlane - changed region is the destination rectangle, clipped by
+// pCompositeClip
+
+static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
+ GCPtr pGC, int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long plane)
+{
+ GC_OP_UNWRAPPER(pDst, pGC, CopyPlane);
+
+ BoxRec box;
+ box.x1 = dstx + pDst->x;
+ box.y1 = dsty + pDst->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ RegionPtr rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, plane);
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ return rgn;
+}
+
+// PolyPoint - changed region is the bounding rect, clipped by pCompositeClip
+
+static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, xPoint *pts)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyPoint);
+
+ if (npt == 0) {
+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
+ return;
+ }
+
+ int minX = pts[0].x;
+ int maxX = pts[0].x;
+ int minY = pts[0].y;
+ int maxY = pts[0].y;
+
+ if (mode == CoordModePrevious) {
+ int x = pts[0].x;
+ int y = pts[0].y;
+
+ for (int 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 (int 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;
+ }
+ }
+
+ BoxRec box;
+ box.x1 = minX + pDrawable->x;
+ box.y1 = minY + pDrawable->y;
+ box.x2 = maxX + 1 + pDrawable->x;
+ box.y2 = maxY + 1 + pDrawable->y;
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// Polylines - changed region is the union of the bounding rects of each line,
+// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP lines,
+// just use the bounding rect of all the lines.
+
+static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode,
+ int npt, DDXPointPtr ppts)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, Polylines);
+
+ if (npt == 0) {
+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
+ return;
+ }
+
+ int nRegRects = npt - 1;
+ xRectangle regRects[MAX_RECTS_PER_OP];
+
+ int lw = pGC->lineWidth;
+ if (lw == 0) lw = 1;
+
+ if (npt == 1)
+ {
+ // a single point
+ nRegRects = 1;
+ regRects[0].x = pDrawable->x + ppts[0].x - lw;
+ regRects[0].y = pDrawable->y + ppts[0].y - lw;
+ regRects[0].width = 2*lw;
+ regRects[0].height = 2*lw;
+ }
+ else
+ {
+ /*
+ * 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
+ */
+
+ int extra = lw / 2;
+ if (pGC->joinStyle == JoinMiter) {
+ extra = 6 * lw;
+ }
+
+ int prevX, prevY, curX, curY;
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+
+ prevX = ppts[0].x + pDrawable->x;
+ prevY = ppts[0].y + pDrawable->y;
+ minX = maxX = prevX;
+ minY = maxY = prevY;
+
+ for (int i = 0; i < nRegRects; i++) {
+ if (mode == CoordModeOrigin) {
+ curX = pDrawable->x + ppts[i+1].x;
+ curY = pDrawable->y + ppts[i+1].y;
+ } else {
+ curX = prevX + ppts[i+1].x;
+ curY = prevY + ppts[i+1].y;
+ }
+
+ if (prevX > curX) {
+ rectX1 = curX - extra;
+ rectX2 = prevX + extra + 1;
+ } else {
+ rectX1 = prevX - extra;
+ rectX2 = curX + extra + 1;
+ }
+
+ if (prevY > curY) {
+ rectY1 = curY - extra;
+ rectY2 = prevY + extra + 1;
+ } else {
+ rectY1 = prevY - extra;
+ rectY2 = curY + extra + 1;
+ }
+
+ if (nRegRects <= MAX_RECTS_PER_OP) {
+ regRects[i].x = rectX1;
+ regRects[i].y = rectY1;
+ regRects[i].width = rectX2 - rectX1;
+ regRects[i].height = rectY2 - rectY1;
+ } else {
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+
+ prevX = curX;
+ prevY = curY;
+ }
+
+ if (nRegRects > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolySegment - changed region is the union of the bounding rects of each
+// segment, clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
+// segments, just use the bounding rect of all the segments.
+
+static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg,
+ xSegment *segs)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolySegment);
+
+ if (nseg == 0) {
+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
+ return;
+ }
+
+ xRectangle regRects[MAX_RECTS_PER_OP];
+ int nRegRects = nseg;
+
+ int lw = pGC->lineWidth;
+ int extra = lw / 2;
+
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+
+ minX = maxX = segs[0].x1;
+ minY = maxY = segs[0].y1;
+
+ for (int i = 0; i < nseg; i++) {
+ if (segs[i].x1 > segs[i].x2) {
+ rectX1 = pDrawable->x + segs[i].x2 - extra;
+ rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
+ } else {
+ rectX1 = pDrawable->x + segs[i].x1 - extra;
+ rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
+ }
+
+ if (segs[i].y1 > segs[i].y2) {
+ rectY1 = pDrawable->y + segs[i].y2 - extra;
+ rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
+ } else {
+ rectY1 = pDrawable->y + segs[i].y1 - extra;
+ rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
+ }
+
+ if (nseg <= MAX_RECTS_PER_OP) {
+ regRects[i].x = rectX1;
+ regRects[i].y = rectY1;
+ regRects[i].width = rectX2 - rectX1;
+ regRects[i].height = rectY2 - rectY1;
+ } else {
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+ }
+
+ if (nseg > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyRectangle - changed region is the union of the bounding rects around
+// each side of the outline rectangles, clipped by pCompositeClip. If there
+// are more than MAX_RECTS_PER_OP rectangles, just use the bounding rect of all
+// the rectangles.
+
+static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle *rects)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyRectangle);
+
+ if (nrects == 0) {
+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
+ return;
+ }
+
+ xRectangle regRects[MAX_RECTS_PER_OP*4];
+ int nRegRects = nrects * 4;
+
+ int lw = pGC->lineWidth;
+ int extra = lw / 2;
+
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+
+ minX = maxX = rects[0].x;
+ minY = maxY = rects[0].y;
+
+ for (int i = 0; i < nrects; i++) {
+ if (nrects <= MAX_RECTS_PER_OP) {
+ 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;
+ } else {
+ rectX1 = pDrawable->x + rects[i].x - extra;
+ rectY1 = pDrawable->y + rects[i].y - extra;
+ rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
+ rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+ }
+
+ if (nrects > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyArc - changed region is the union of bounding rects around each arc,
+// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP
+// arcs, just use the bounding rect of all the arcs.
+
+static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+ xArc *arcs)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyArc);
+
+ if (narcs == 0) {
+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
+ return;
+ }
+
+ xRectangle regRects[MAX_RECTS_PER_OP];
+ int nRegRects = narcs;
+
+ int lw = pGC->lineWidth;
+ if (lw == 0) lw = 1;
+ int extra = lw / 2;
+
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+
+ minX = maxX = arcs[0].x;
+ minY = maxY = arcs[0].y;
+
+ for (int i = 0; i < narcs; i++) {
+ if (narcs <= MAX_RECTS_PER_OP) {
+ regRects[i].x = arcs[i].x - extra + pDrawable->x;
+ regRects[i].y = arcs[i].y - extra + pDrawable->y;
+ regRects[i].width = arcs[i].width + lw;
+ regRects[i].height = arcs[i].height + lw;
+ } else {
+ rectX1 = pDrawable->x + arcs[i].x - extra;
+ rectY1 = pDrawable->y + arcs[i].y - extra;
+ rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
+ rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+ }
+
+ if (narcs > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+
+// FillPolygon - changed region is the bounding rect around the polygon,
+// clipped by pCompositeClip
+
+static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
+ int mode, int count, DDXPointPtr pts)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, FillPolygon);
+
+ if (count == 0) {
+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
+ return;
+ }
+
+ int minX = pts[0].x;
+ int maxX = pts[0].x;
+ int minY = pts[0].y;
+ int maxY = pts[0].y;
+
+ if (mode == CoordModePrevious) {
+ int x = pts[0].x;
+ int y = pts[0].y;
+
+ for (int 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 (int 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;
+ }
+ }
+
+ BoxRec box;
+ box.x1 = minX + pDrawable->x;
+ box.y1 = minY + pDrawable->y;
+ box.x2 = maxX + 1 + pDrawable->x;
+ box.y2 = maxY + 1 + pDrawable->y;
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyFillRect - changed region is the union of the rectangles, clipped by
+// pCompositeClip. If there are more than MAX_RECTS_PER_OP rectangles, just
+// use the bounding rect of all the rectangles.
+
+static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects,
+ xRectangle *rects)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillRect);
+
+ if (nrects == 0) {
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
+ return;
+ }
+
+ xRectangle regRects[MAX_RECTS_PER_OP];
+ int nRegRects = nrects;
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+ minX = maxX = rects[0].x;
+ minY = maxY = rects[0].y;
+
+ for (int i = 0; i < nrects; i++) {
+ if (nrects <= MAX_RECTS_PER_OP) {
+ 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;
+ } else {
+ rectX1 = pDrawable->x + rects[i].x;
+ rectY1 = pDrawable->y + rects[i].y;
+ rectX2 = pDrawable->x + rects[i].x + rects[i].width;
+ rectY2 = pDrawable->y + rects[i].y + rects[i].height;
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+ }
+
+ if (nrects > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyFillArc - changed region is the union of bounding rects around each arc,
+// clipped by pCompositeClip. If there are more than MAX_RECTS_PER_OP arcs,
+// just use the bounding rect of all the arcs.
+
+static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs,
+ xArc *arcs)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyFillArc);
+
+ if (narcs == 0) {
+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
+ return;
+ }
+
+ xRectangle regRects[MAX_RECTS_PER_OP];
+ int nRegRects = narcs;
+
+ int lw = pGC->lineWidth;
+ if (lw == 0) lw = 1;
+ int extra = lw / 2;
+
+ int rectX1, rectY1, rectX2, rectY2;
+ int minX, minY, maxX, maxY;
+
+ minX = maxX = arcs[0].x;
+ minY = maxY = arcs[0].y;
+
+ for (int i = 0; i < narcs; i++) {
+ if (narcs <= MAX_RECTS_PER_OP) {
+ regRects[i].x = arcs[i].x - extra + pDrawable->x;
+ regRects[i].y = arcs[i].y - extra + pDrawable->y;
+ regRects[i].width = arcs[i].width + lw;
+ regRects[i].height = arcs[i].height + lw;
+ } else {
+ rectX1 = pDrawable->x + arcs[i].x - extra;
+ rectY1 = pDrawable->y + arcs[i].y - extra;
+ rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
+ rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
+ if (rectX1 < minX) minX = rectX1;
+ if (rectY1 < minY) minY = rectY1;
+ if (rectX2 > maxX) maxX = rectX2;
+ if (rectY2 > maxY) maxY = rectY2;
+ }
+ }
+
+ if (narcs > MAX_RECTS_PER_OP) {
+ regRects[0].x = minX;
+ regRects[0].y = minY;
+ regRects[0].width = maxX - minX;
+ regRects[0].height = maxY - minY;
+ nRegRects = 1;
+ }
+
+ RegionHelper changed(pScreen, nRegRects, regRects);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// GetTextBoundingRect - calculate a bounding rectangle around n chars of a
+// font. Not particularly accurate, but good enough.
+
+static void GetTextBoundingRect(DrawablePtr pDrawable, FontPtr font, int x,
+ int y, int nchars, BoxPtr box)
+{
+ int ascent = __rfbmax(FONTASCENT(font), FONTMAXBOUNDS(font, ascent));
+ int descent = __rfbmax(FONTDESCENT(font), FONTMAXBOUNDS(font, descent));
+ int charWidth = __rfbmax(FONTMAXBOUNDS(font,rightSideBearing),
+ FONTMAXBOUNDS(font,characterWidth));
+
+ box->x1 = pDrawable->x + x;
+ box->y1 = pDrawable->y + y - ascent;
+ box->x2 = box->x1 + charWidth * nchars;
+ box->y2 = box->y1 + ascent + descent;
+
+ if (FONTMINBOUNDS(font,leftSideBearing) < 0)
+ box->x1 += FONTMINBOUNDS(font,leftSideBearing);
+}
+
+// PolyText8 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, char *chars)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyText8);
+
+ if (count == 0)
+ return (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ int ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ return ret;
+}
+
+// PolyText16 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyText16);
+
+ if (count == 0)
+ return (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ int ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+
+ return ret;
+}
+
+// ImageText8 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, char *chars)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, ImageText8);
+
+ if (count == 0) {
+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+ return;
+ }
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// ImageText16 - changed region is bounding rect around count chars, clipped by
+// pCompositeClip
+
+static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, ImageText16);
+
+ if (count == 0) {
+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+ return;
+ }
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// ImageGlyphBlt - changed region is bounding rect around nglyph chars, clipped
+// by pCompositeClip
+
+static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, ImageGlyphBlt);
+
+ if (nglyph == 0) {
+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
+ return;
+ }
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PolyGlyphBlt - changed region is bounding rect around nglyph chars, clipped
+// by pCompositeClip
+
+static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x,
+ int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PolyGlyphBlt);
+
+ if (nglyph == 0) {
+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
+ return;
+ }
+
+ BoxRec box;
+ GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box);
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
+
+// PushPixels - changed region is the given rectangle, clipped by
+// pCompositeClip
+
+static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap,
+ DrawablePtr pDrawable, int w, int h, int x,
+ int y)
+{
+ GC_OP_UNWRAPPER(pDrawable, pGC, PushPixels);
+
+ BoxRec box;
+ box.x1 = x + pDrawable->x;
+ box.y1 = y + pDrawable->y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+
+ RegionHelper changed(pScreen, &box, 0);
+
+ REGION_INTERSECT(pScreen, changed.reg, changed.reg, COMPOSITE_CLIP(pGC));
+
+ (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
+
+ vncHooksScreen->desktop->add_changed(changed.reg);
+}
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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 __VNCHOOKS_H__
+#define __VNCHOOKS_H__
+
+extern "C" {
+#include <screenint.h>
+ extern Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop);
+}
+
+#endif
--- /dev/null
+/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
+ */
+/* This is the xf86 module code for the vnc extension.
+ */
+
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+
+extern "C" {
+#define class c_class
+#define private c_private
+#define bool c_bool
+#define new c_new
+#include "xf86.h"
+#include "xf86Module.h"
+#undef class
+#undef private
+#undef bool
+#undef new
+
+using namespace rfb;
+
+extern void vncExtensionInit();
+static void vncExtensionInitWithParams(INITARGS);
+
+#ifdef XFree86LOADER
+
+static MODULESETUPPROTO(vncSetup);
+
+ExtensionModule vncExt =
+{
+ vncExtensionInitWithParams,
+ "VNC",
+ NULL,
+ NULL,
+ NULL
+};
+
+static XF86ModuleVersionInfo vncVersRec =
+{
+ "vnc",
+ "Constantin Kaplinsky",
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ 1, 0, 0,
+ ABI_CLASS_EXTENSION, /* needs the server extension ABI */
+ ABI_EXTENSION_VERSION,
+ MOD_CLASS_EXTENSION,
+ {0,0,0,0}
+};
+
+XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };
+
+static pointer
+vncSetup(pointer module, pointer opts, int *errmaj, int *errmin) {
+ LoadExtension(&vncExt, FALSE);
+ /* Need a non-NULL return value to indicate success */
+ return (pointer)1;
+}
+
+static void vncExtensionInitWithParams(INITARGS)
+{
+ rfb::initStdIOLoggers();
+ rfb::LogWriter::setLogParams("*:stderr:30");
+
+ for (int scr = 0; scr < screenInfo.numScreens; scr++) {
+ ScrnInfoPtr pScrn = xf86Screens[scr];
+
+ for (ParameterIterator i(Configuration::global()); i.param; i.next()) {
+ char* val = xf86FindOptionValue(pScrn->options, i.param->getName());
+ if (val)
+ i.param->setParam(val);
+ }
+ }
+
+ vncExtensionInit();
+}
+
+#endif /* XFree86LOADER */
+}
--- /dev/null
+/* Copyright (c) 1993 X Consortium
+ Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice 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 <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+#include <network/TcpSocket.h>
+#include "vncExtInit.h"
+
+extern "C" {
+#define class c_class
+#define public c_public
+#define xor c_xor
+#define and c_and
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+#include <stdio.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 "mi.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#define new New
+#include "micmap.h"
+#undef new
+#include <sys/types.h>
+#ifdef HAS_MMAP
+#include <sys/mman.h>
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#endif /* HAS_MMAP */
+#include <sys/stat.h>
+#include <errno.h>
+#ifndef WIN32
+#include <sys/param.h>
+#endif
+#include <X11/XWDFile.h>
+#ifdef HAS_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif /* HAS_SHM */
+#include "dix.h"
+#include "miline.h"
+#include "inputstr.h"
+#include "keysym.h"
+ extern int defaultColorVisualClass;
+ extern char buildtime[];
+#undef class
+#undef public
+#undef xor
+#undef and
+}
+
+#define XVNCVERSION "TightVNC 1.5 series"
+#define XVNCCOPYRIGHT ("Copyright (C) 2002-2005 RealVNC Ltd.\n" \
+ "Copyright (C) 2000-2006 Constantin Kaplinsky\n" \
+ "Copyright (C) 2004-2006 Peter Astrand, Cendio AB\n" \
+ "See http://www.tightvnc.com for information on TightVNC.\n")
+
+
+extern char *display;
+extern int monitorResolution;
+
+#define VFB_DEFAULT_WIDTH 1024
+#define VFB_DEFAULT_HEIGHT 768
+#define VFB_DEFAULT_DEPTH 16
+#define VFB_DEFAULT_WHITEPIXEL 0xffff
+#define VFB_DEFAULT_BLACKPIXEL 0
+#define VFB_DEFAULT_LINEBIAS 0
+#define XWD_WINDOW_NAME_LEN 60
+
+typedef struct
+{
+ int scrnum;
+ int width;
+ int paddedBytesWidth;
+ int paddedWidth;
+ int height;
+ int depth;
+ int bitsPerPixel;
+ int sizeInBytes;
+ int ncolors;
+ char *pfbMemory;
+ XWDColor *pXWDCmap;
+ XWDFileHeader *pXWDHeader;
+ Pixel blackPixel;
+ Pixel whitePixel;
+ unsigned int lineBias;
+ CloseScreenProcPtr closeScreen;
+
+#ifdef HAS_MMAP
+ int mmap_fd;
+ char mmap_file[MAXPATHLEN];
+#endif
+
+#ifdef HAS_SHM
+ int shmid;
+#endif
+
+ Bool pixelFormatDefined;
+ Bool rgbNotBgr;
+ int redBits, greenBits, blueBits;
+
+} vfbScreenInfo, *vfbScreenInfoPtr;
+
+static int vfbNumScreens;
+static vfbScreenInfo vfbScreens[MAXSCREENS];
+static Bool vfbPixmapDepths[33];
+#ifdef HAS_MMAP
+static char *pfbdir = NULL;
+#endif
+typedef enum { NORMAL_MEMORY_FB, SHARED_MEMORY_FB, MMAPPED_FILE_FB } fbMemType;
+static fbMemType fbmemtype = NORMAL_MEMORY_FB;
+static char needswap = 0;
+static int lastScreen = -1;
+static Bool Render = TRUE;
+
+static bool displaySpecified = false;
+static bool wellKnownSocketsCreated = false;
+static char displayNumStr[16];
+
+#define swapcopy16(_dst, _src) \
+ if (needswap) { CARD16 _s = _src; cpswaps(_s, _dst); } \
+ else _dst = _src;
+
+#define swapcopy32(_dst, _src) \
+ if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
+ else _dst = _src;
+
+
+static void
+vfbInitializePixmapDepths(void)
+{
+ int i;
+ vfbPixmapDepths[1] = TRUE; /* always need bitmaps */
+ for (i = 2; i <= 32; i++)
+ vfbPixmapDepths[i] = FALSE;
+}
+
+static void
+vfbInitializeDefaultScreens(void)
+{
+ int i;
+
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ vfbScreens[i].scrnum = i;
+ vfbScreens[i].width = VFB_DEFAULT_WIDTH;
+ vfbScreens[i].height = VFB_DEFAULT_HEIGHT;
+ vfbScreens[i].depth = VFB_DEFAULT_DEPTH;
+ vfbScreens[i].blackPixel = VFB_DEFAULT_BLACKPIXEL;
+ vfbScreens[i].whitePixel = VFB_DEFAULT_WHITEPIXEL;
+ vfbScreens[i].lineBias = VFB_DEFAULT_LINEBIAS;
+ vfbScreens[i].pixelFormatDefined = FALSE;
+ vfbScreens[i].pfbMemory = NULL;
+ }
+ vfbNumScreens = 1;
+}
+
+static int
+vfbBitsPerPixel(int depth)
+{
+ if (depth == 1) return 1;
+ else if (depth <= 8) return 8;
+ else if (depth <= 16) return 16;
+ else return 32;
+}
+
+
+extern "C" {
+
+ void ddxGiveUp()
+ {
+ int i;
+
+ /* clean up the framebuffers */
+
+ switch (fbmemtype)
+ {
+#ifdef HAS_MMAP
+ case MMAPPED_FILE_FB:
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+ if (-1 == unlink(vfbScreens[i].mmap_file))
+ {
+ perror("unlink");
+ ErrorF("unlink %s failed, errno %d",
+ vfbScreens[i].mmap_file, errno);
+ }
+ }
+ break;
+#else /* HAS_MMAP */
+ case MMAPPED_FILE_FB:
+ break;
+#endif /* HAS_MMAP */
+
+#ifdef HAS_SHM
+ case SHARED_MEMORY_FB:
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+ if (-1 == shmdt((char *)vfbScreens[i].pXWDHeader))
+ {
+ perror("shmdt");
+ ErrorF("shmdt failed, errno %d", errno);
+ }
+ }
+ break;
+#else /* HAS_SHM */
+ case SHARED_MEMORY_FB:
+ break;
+#endif /* HAS_SHM */
+
+ case NORMAL_MEMORY_FB:
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+ Xfree(vfbScreens[i].pXWDHeader);
+ }
+ break;
+ }
+}
+
+void
+AbortDDX()
+{
+ ddxGiveUp();
+}
+
+#ifdef __DARWIN__
+void
+DarwinHandleGUI(int argc, char *argv[])
+{
+}
+
+void GlxExtensionInit();
+void GlxWrapInitVisuals(void *procPtr);
+
+void
+DarwinGlxExtensionInit()
+{
+ GlxExtensionInit();
+}
+
+void
+DarwinGlxWrapInitVisuals(
+ void *procPtr)
+{
+ GlxWrapInitVisuals(procPtr);
+}
+#endif
+
+void
+OsVendorInit()
+{
+}
+
+void
+OsVendorFatalError()
+{
+}
+
+void ddxBeforeReset(void)
+{
+ return;
+}
+
+void
+ddxUseMsg()
+{
+ ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
+ ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
+ VENDOR_STRING);
+ ErrorF("-screen scrn WxHxD set screen's width, height, depth\n");
+ ErrorF("-pixdepths list-of-int support given pixmap depths\n");
+#ifdef RENDER
+ ErrorF("+/-render turn on/off RENDER extension support"
+ "(default on)\n");
+#endif
+ ErrorF("-linebias n adjust thin line pixelization\n");
+ ErrorF("-blackpixel n pixel value for black\n");
+ ErrorF("-whitepixel n pixel value for white\n");
+
+#ifdef HAS_MMAP
+ ErrorF("-fbdir directory put framebuffers in mmap'ed files in directory\n");
+#endif
+
+#ifdef HAS_SHM
+ ErrorF("-shmem put framebuffers in shared memory\n");
+#endif
+
+ ErrorF("-geometry WxH set screen 0's width, height\n");
+ ErrorF("-depth D set screen 0's depth\n");
+ ErrorF("-pixelformat fmt set pixel format (rgbNNN or bgrNNN)\n");
+ ErrorF("-inetd has been launched from inetd\n");
+ ErrorF("\nVNC parameters:\n");
+
+ fprintf(stderr,"\n"
+ "Parameters can be turned on with -<param> or off with -<param>=0\n"
+ "Parameters which take a value can be specified as "
+ "-<param> <value>\n"
+ "Other valid forms are <param>=<value> -<param>=<value> "
+ "--<param>=<value>\n"
+ "Parameter names are case-insensitive. The parameters are:\n\n");
+ rfb::Configuration::listParams(79, 14);
+ }
+}
+
+/* ddxInitGlobals - called by |InitGlobals| from os/util.c */
+void ddxInitGlobals(void)
+{
+}
+
+static
+bool displayNumFree(int num)
+{
+ try {
+ network::TcpListener l(6000+num);
+ } catch (rdr::Exception& e) {
+ return false;
+ }
+ char file[256];
+ sprintf(file, "/tmp/.X%d-lock", num);
+ if (access(file, F_OK) == 0) return false;
+ sprintf(file, "/tmp/.X11-unix/X%d", num);
+ if (access(file, F_OK) == 0) return false;
+ sprintf(file, "/usr/spool/sockets/X11/%d", num);
+ if (access(file, F_OK) == 0) return false;
+ return true;
+}
+
+int
+ddxProcessArgument(int argc, char *argv[], int i)
+{
+ static Bool firstTime = TRUE;
+
+ if (firstTime)
+ {
+ vfbInitializeDefaultScreens();
+ vfbInitializePixmapDepths();
+ firstTime = FALSE;
+ rfb::initStdIOLoggers();
+ rfb::LogWriter::setLogParams("*:stderr:30");
+ }
+
+ if (argv[i][0] == ':')
+ displaySpecified = true;
+
+ if (strcmp (argv[i], "-screen") == 0) /* -screen n WxHxD */
+ {
+ int screenNum;
+ if (i + 2 >= argc) UseMsg();
+ screenNum = atoi(argv[i+1]);
+ if (screenNum < 0 || screenNum >= MAXSCREENS)
+ {
+ ErrorF("Invalid screen number %d\n", screenNum);
+ UseMsg();
+ }
+ if (3 != sscanf(argv[i+2], "%dx%dx%d",
+ &vfbScreens[screenNum].width,
+ &vfbScreens[screenNum].height,
+ &vfbScreens[screenNum].depth))
+ {
+ ErrorF("Invalid screen configuration %s\n", argv[i+2]);
+ UseMsg();
+ }
+
+ if (screenNum >= vfbNumScreens)
+ vfbNumScreens = screenNum + 1;
+ lastScreen = screenNum;
+ return 3;
+ }
+
+ if (strcmp (argv[i], "-pixdepths") == 0) /* -pixdepths list-of-depth */
+ {
+ int depth, ret = 1;
+
+ if (++i >= argc) UseMsg();
+ while ((i < argc) && (depth = atoi(argv[i++])) != 0)
+ {
+ if (depth < 0 || depth > 32)
+ {
+ ErrorF("Invalid pixmap depth %d\n", depth);
+ UseMsg();
+ }
+ vfbPixmapDepths[depth] = TRUE;
+ ret++;
+ }
+ return ret;
+ }
+
+ if (strcmp (argv[i], "+render") == 0) /* +render */
+ {
+ Render = TRUE;
+ return 1;
+ }
+
+ if (strcmp (argv[i], "-render") == 0) /* -render */
+ {
+ Render = FALSE;
+ return 1;
+ }
+
+ if (strcmp (argv[i], "-blackpixel") == 0) /* -blackpixel n */
+ {
+ Pixel pix;
+ if (++i >= argc) UseMsg();
+ pix = atoi(argv[i]);
+ if (-1 == lastScreen)
+ {
+ int i;
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ vfbScreens[i].blackPixel = pix;
+ }
+ }
+ else
+ {
+ vfbScreens[lastScreen].blackPixel = pix;
+ }
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-whitepixel") == 0) /* -whitepixel n */
+ {
+ Pixel pix;
+ if (++i >= argc) UseMsg();
+ pix = atoi(argv[i]);
+ if (-1 == lastScreen)
+ {
+ int i;
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ vfbScreens[i].whitePixel = pix;
+ }
+ }
+ else
+ {
+ vfbScreens[lastScreen].whitePixel = pix;
+ }
+ return 2;
+ }
+
+ if (strcmp (argv[i], "-linebias") == 0) /* -linebias n */
+ {
+ unsigned int linebias;
+ if (++i >= argc) UseMsg();
+ linebias = atoi(argv[i]);
+ if (-1 == lastScreen)
+ {
+ int i;
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ vfbScreens[i].lineBias = linebias;
+ }
+ }
+ else
+ {
+ vfbScreens[lastScreen].lineBias = linebias;
+ }
+ return 2;
+ }
+
+#ifdef HAS_MMAP
+ if (strcmp (argv[i], "-fbdir") == 0) /* -fbdir directory */
+ {
+ if (++i >= argc) UseMsg();
+ pfbdir = argv[i];
+ fbmemtype = MMAPPED_FILE_FB;
+ return 2;
+ }
+#endif /* HAS_MMAP */
+
+#ifdef HAS_SHM
+ if (strcmp (argv[i], "-shmem") == 0) /* -shmem */
+ {
+ fbmemtype = SHARED_MEMORY_FB;
+ return 1;
+ }
+#endif
+
+ if (strcmp(argv[i], "-geometry") == 0)
+ {
+ if (++i >= argc) UseMsg();
+ if (sscanf(argv[i],"%dx%d",&vfbScreens[0].width,
+ &vfbScreens[0].height) != 2) {
+ ErrorF("Invalid geometry %s\n", argv[i]);
+ UseMsg();
+ }
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-depth") == 0)
+ {
+ if (++i >= argc) UseMsg();
+ vfbScreens[0].depth = atoi(argv[i]);
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-pixelformat") == 0)
+ {
+ char rgbbgr[4];
+ int bits1, bits2, bits3;
+ if (++i >= argc) UseMsg();
+ if (sscanf(argv[i], "%3s%1d%1d%1d", rgbbgr,&bits1,&bits2,&bits3) < 4) {
+ ErrorF("Invalid pixel format %s\n", argv[i]);
+ UseMsg();
+ }
+
+#define SET_PIXEL_FORMAT(vfbScreen) \
+ (vfbScreen).pixelFormatDefined = TRUE; \
+ (vfbScreen).depth = bits1 + bits2 + bits3; \
+ (vfbScreen).greenBits = bits2; \
+ if (strcasecmp(rgbbgr, "bgr") == 0) { \
+ (vfbScreen).rgbNotBgr = FALSE; \
+ (vfbScreen).redBits = bits3; \
+ (vfbScreen).blueBits = bits1; \
+ } else if (strcasecmp(rgbbgr, "rgb") == 0) { \
+ (vfbScreen).rgbNotBgr = TRUE; \
+ (vfbScreen).redBits = bits1; \
+ (vfbScreen).blueBits = bits3; \
+ } else { \
+ ErrorF("Invalid pixel format %s\n", argv[i]); \
+ UseMsg(); \
+ }
+
+ if (-1 == lastScreen)
+ {
+ int i;
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ SET_PIXEL_FORMAT(vfbScreens[i]);
+ }
+ }
+ else
+ {
+ SET_PIXEL_FORMAT(vfbScreens[lastScreen]);
+ }
+
+ return 2;
+ }
+
+ if (strcmp(argv[i], "-inetd") == 0)
+ {
+ dup2(0,3);
+ vncInetdSock = 3;
+ close(2);
+
+ if (!displaySpecified) {
+ int port = network::TcpSocket::getSockPort(vncInetdSock);
+ int displayNum = port - 5900;
+ if (displayNum < 0 || displayNum > 99 || !displayNumFree(displayNum)) {
+ for (displayNum = 1; displayNum < 100; displayNum++)
+ if (displayNumFree(displayNum)) break;
+
+ if (displayNum == 100)
+ FatalError("Xvnc error: no free display number for -inetd");
+ }
+
+ display = displayNumStr;
+ sprintf(displayNumStr, "%d", displayNum);
+ }
+
+ return 1;
+ }
+
+ if (rfb::Configuration::setParam(argv[i]))
+ return 1;
+
+ if (argv[i][0] == '-' && i+1 < argc) {
+ if (rfb::Configuration::setParam(&argv[i][1], argv[i+1]))
+ return 2;
+ }
+
+ return 0;
+}
+
+#ifdef DDXTIME /* from ServerOSDefines */
+CARD32
+GetTimeInMillis()
+{
+ struct timeval tp;
+
+ X_GETTIMEOFDAY(&tp);
+ return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
+}
+#endif
+
+static ColormapPtr InstalledMaps[MAXSCREENS];
+
+static int
+vfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
+{
+ /* By the time we are processing requests, we can guarantee that there
+ * is always a colormap installed */
+ *pmaps = InstalledMaps[pScreen->myNum]->mid;
+ return (1);
+}
+
+
+static void
+vfbInstallColormap(ColormapPtr pmap)
+{
+ int index = pmap->pScreen->myNum;
+ ColormapPtr oldpmap = InstalledMaps[index];
+
+ if (pmap != oldpmap)
+ {
+ int entries;
+ XWDFileHeader *pXWDHeader;
+ XWDColor *pXWDCmap;
+ VisualPtr pVisual;
+ Pixel * ppix;
+ xrgb * prgb;
+ xColorItem *defs;
+ int i;
+
+ if(oldpmap != (ColormapPtr)None)
+ WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
+ /* Install pmap */
+ InstalledMaps[index] = pmap;
+ WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
+
+ entries = pmap->pVisual->ColormapEntries;
+ pXWDHeader = vfbScreens[pmap->pScreen->myNum].pXWDHeader;
+ pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
+ pVisual = pmap->pVisual;
+
+ swapcopy32(pXWDHeader->visual_class, pVisual->c_class);
+ swapcopy32(pXWDHeader->red_mask, pVisual->redMask);
+ swapcopy32(pXWDHeader->green_mask, pVisual->greenMask);
+ swapcopy32(pXWDHeader->blue_mask, pVisual->blueMask);
+ swapcopy32(pXWDHeader->bits_per_rgb, pVisual->bitsPerRGBValue);
+ swapcopy32(pXWDHeader->colormap_entries, pVisual->ColormapEntries);
+
+ ppix = (Pixel *)ALLOCATE_LOCAL(entries * sizeof(Pixel));
+ prgb = (xrgb *)ALLOCATE_LOCAL(entries * sizeof(xrgb));
+ defs = (xColorItem *)ALLOCATE_LOCAL(entries * sizeof(xColorItem));
+
+ for (i = 0; i < entries; i++) ppix[i] = i;
+ /* XXX truecolor */
+ QueryColors(pmap, entries, ppix, prgb);
+
+ for (i = 0; i < entries; i++) { /* convert xrgbs to xColorItems */
+ defs[i].pixel = ppix[i] & 0xff; /* change pixel to index */
+ defs[i].red = prgb[i].red;
+ defs[i].green = prgb[i].green;
+ defs[i].blue = prgb[i].blue;
+ defs[i].flags = DoRed|DoGreen|DoBlue;
+ }
+ (*pmap->pScreen->StoreColors)(pmap, entries, defs);
+
+ DEALLOCATE_LOCAL(ppix);
+ DEALLOCATE_LOCAL(prgb);
+ DEALLOCATE_LOCAL(defs);
+ }
+}
+
+static void
+vfbUninstallColormap(ColormapPtr pmap)
+{
+ ColormapPtr curpmap = InstalledMaps[pmap->pScreen->myNum];
+
+ if(pmap == curpmap)
+ {
+ if (pmap->mid != pmap->pScreen->defColormap)
+ {
+ curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
+ RT_COLORMAP);
+ (*pmap->pScreen->InstallColormap)(curpmap);
+ }
+ }
+}
+
+static void
+vfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs)
+{
+ XWDColor *pXWDCmap;
+ int i;
+
+ if (pmap != InstalledMaps[pmap->pScreen->myNum])
+ {
+ return;
+ }
+
+ pXWDCmap = vfbScreens[pmap->pScreen->myNum].pXWDCmap;
+
+ if ((pmap->pVisual->c_class | DynamicClass) == DirectColor)
+ {
+ return;
+ }
+
+ for (i = 0; i < ndef; i++)
+ {
+ if (pdefs[i].flags & DoRed)
+ {
+ swapcopy16(pXWDCmap[pdefs[i].pixel].red, pdefs[i].red);
+ }
+ if (pdefs[i].flags & DoGreen)
+ {
+ swapcopy16(pXWDCmap[pdefs[i].pixel].green, pdefs[i].green);
+ }
+ if (pdefs[i].flags & DoBlue)
+ {
+ swapcopy16(pXWDCmap[pdefs[i].pixel].blue, pdefs[i].blue);
+ }
+ }
+}
+
+static Bool
+vfbSaveScreen(ScreenPtr pScreen, int on)
+{
+ return TRUE;
+}
+
+#ifdef HAS_MMAP
+
+/* this flushes any changes to the screens out to the mmapped file */
+static void
+vfbBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadmask)
+{
+ int i;
+
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+#ifdef MS_ASYNC
+ if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
+ (size_t)vfbScreens[i].sizeInBytes, MS_ASYNC))
+#else
+ /* silly NetBSD and who else? */
+ if (-1 == msync((caddr_t)vfbScreens[i].pXWDHeader,
+ (size_t)vfbScreens[i].sizeInBytes))
+#endif
+ {
+ perror("msync");
+ ErrorF("msync failed, errno %d", errno);
+ }
+ }
+}
+
+
+static void
+vfbWakeupHandler(pointer blockData, int result, pointer pReadmask)
+{
+}
+
+
+static void
+vfbAllocateMmappedFramebuffer(vfbScreenInfoPtr pvfb)
+{
+#define DUMMY_BUFFER_SIZE 65536
+ char dummyBuffer[DUMMY_BUFFER_SIZE];
+ int currentFileSize, writeThisTime;
+
+ sprintf(pvfb->mmap_file, "%s/Xvfb_screen%d", pfbdir, pvfb->scrnum);
+ if (-1 == (pvfb->mmap_fd = open(pvfb->mmap_file, O_CREAT|O_RDWR, 0666)))
+ {
+ perror("open");
+ ErrorF("open %s failed, errno %d", pvfb->mmap_file, errno);
+ return;
+ }
+
+ /* Extend the file to be the proper size */
+
+ bzero(dummyBuffer, DUMMY_BUFFER_SIZE);
+ for (currentFileSize = 0;
+ currentFileSize < pvfb->sizeInBytes;
+ currentFileSize += writeThisTime)
+ {
+ writeThisTime = min(DUMMY_BUFFER_SIZE,
+ pvfb->sizeInBytes - currentFileSize);
+ if (-1 == write(pvfb->mmap_fd, dummyBuffer, writeThisTime))
+ {
+ perror("write");
+ ErrorF("write %s failed, errno %d", pvfb->mmap_file, errno);
+ return;
+ }
+ }
+
+ /* try to mmap the file */
+
+ pvfb->pXWDHeader = (XWDFileHeader *)mmap((caddr_t)NULL, pvfb->sizeInBytes,
+ PROT_READ|PROT_WRITE,
+ MAP_FILE|MAP_SHARED,
+ pvfb->mmap_fd, 0);
+ if (-1 == (long)pvfb->pXWDHeader)
+ {
+ perror("mmap");
+ ErrorF("mmap %s failed, errno %d", pvfb->mmap_file, errno);
+ pvfb->pXWDHeader = NULL;
+ return;
+ }
+
+ if (!RegisterBlockAndWakeupHandlers(vfbBlockHandler, vfbWakeupHandler,
+ NULL))
+ {
+ pvfb->pXWDHeader = NULL;
+ }
+}
+#endif /* HAS_MMAP */
+
+
+#ifdef HAS_SHM
+static void
+vfbAllocateSharedMemoryFramebuffer(vfbScreenInfoPtr pvfb)
+{
+ /* create the shared memory segment */
+
+ pvfb->shmid = shmget(IPC_PRIVATE, pvfb->sizeInBytes, IPC_CREAT|0777);
+ if (pvfb->shmid < 0)
+ {
+ perror("shmget");
+ ErrorF("shmget %d bytes failed, errno %d", pvfb->sizeInBytes, errno);
+ return;
+ }
+
+ /* try to attach it */
+
+ pvfb->pXWDHeader = (XWDFileHeader *)shmat(pvfb->shmid, 0, 0);
+ if (-1 == (long)pvfb->pXWDHeader)
+ {
+ perror("shmat");
+ ErrorF("shmat failed, errno %d", errno);
+ pvfb->pXWDHeader = NULL;
+ return;
+ }
+
+ ErrorF("screen %d shmid %d\n", pvfb->scrnum, pvfb->shmid);
+}
+#endif /* HAS_SHM */
+
+
+static char *
+vfbAllocateFramebufferMemory(vfbScreenInfoPtr pvfb)
+{
+ if (pvfb->pfbMemory) return pvfb->pfbMemory; /* already done */
+
+ pvfb->sizeInBytes = pvfb->paddedBytesWidth * pvfb->height;
+
+ /* Calculate how many entries in colormap. This is rather bogus, because
+ * the visuals haven't even been set up yet, but we need to know because we
+ * have to allocate space in the file for the colormap. The number 10
+ * below comes from the MAX_PSEUDO_DEPTH define in cfbcmap.c.
+ */
+
+ if (pvfb->depth <= 10)
+ { /* single index colormaps */
+ pvfb->ncolors = 1 << pvfb->depth;
+ }
+ else
+ { /* decomposed colormaps */
+ int nplanes_per_color_component = pvfb->depth / 3;
+ if (pvfb->depth % 3) nplanes_per_color_component++;
+ pvfb->ncolors = 1 << nplanes_per_color_component;
+ }
+
+ /* add extra bytes for XWDFileHeader, window name, and colormap */
+
+ pvfb->sizeInBytes += SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN +
+ pvfb->ncolors * SIZEOF(XWDColor);
+
+ pvfb->pXWDHeader = NULL;
+ switch (fbmemtype)
+ {
+#ifdef HAS_MMAP
+ case MMAPPED_FILE_FB: vfbAllocateMmappedFramebuffer(pvfb); break;
+#else
+ case MMAPPED_FILE_FB: break;
+#endif
+
+#ifdef HAS_SHM
+ case SHARED_MEMORY_FB: vfbAllocateSharedMemoryFramebuffer(pvfb); break;
+#else
+ case SHARED_MEMORY_FB: break;
+#endif
+
+ case NORMAL_MEMORY_FB:
+ pvfb->pXWDHeader = (XWDFileHeader *)Xalloc(pvfb->sizeInBytes);
+ break;
+ }
+
+ if (pvfb->pXWDHeader)
+ {
+ pvfb->pXWDCmap = (XWDColor *)((char *)pvfb->pXWDHeader
+ + SIZEOF(XWDheader) + XWD_WINDOW_NAME_LEN);
+ pvfb->pfbMemory = (char *)(pvfb->pXWDCmap + pvfb->ncolors);
+
+ return pvfb->pfbMemory;
+ }
+ else
+ return NULL;
+}
+
+static void
+vfbWriteXWDFileHeader(ScreenPtr pScreen)
+{
+ vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
+ XWDFileHeader *pXWDHeader = pvfb->pXWDHeader;
+ char hostname[XWD_WINDOW_NAME_LEN];
+ unsigned long swaptest = 1;
+ int i;
+
+ needswap = *(char *) &swaptest;
+
+ pXWDHeader->header_size = (char *)pvfb->pXWDCmap - (char *)pvfb->pXWDHeader;
+ pXWDHeader->file_version = XWD_FILE_VERSION;
+
+ pXWDHeader->pixmap_format = ZPixmap;
+ pXWDHeader->pixmap_depth = pvfb->depth;
+ pXWDHeader->pixmap_height = pXWDHeader->window_height = pvfb->height;
+ pXWDHeader->xoffset = 0;
+ pXWDHeader->byte_order = IMAGE_BYTE_ORDER;
+ pXWDHeader->bitmap_bit_order = BITMAP_BIT_ORDER;
+#ifndef INTERNAL_VS_EXTERNAL_PADDING
+ pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->width;
+ pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT;
+ pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD;
+#else
+ pXWDHeader->pixmap_width = pXWDHeader->window_width = pvfb->paddedWidth;
+ pXWDHeader->bitmap_unit = BITMAP_SCANLINE_UNIT_PROTO;
+ pXWDHeader->bitmap_pad = BITMAP_SCANLINE_PAD_PROTO;
+#endif
+ pXWDHeader->bits_per_pixel = pvfb->bitsPerPixel;
+ pXWDHeader->bytes_per_line = pvfb->paddedBytesWidth;
+ pXWDHeader->ncolors = pvfb->ncolors;
+
+ /* visual related fields are written when colormap is installed */
+
+ pXWDHeader->window_x = pXWDHeader->window_y = 0;
+ pXWDHeader->window_bdrwidth = 0;
+
+ /* write xwd "window" name: Xvfb hostname:server.screen */
+
+ if (-1 == gethostname(hostname, sizeof(hostname)))
+ hostname[0] = 0;
+ else
+ hostname[XWD_WINDOW_NAME_LEN-1] = 0;
+ sprintf((char *)(pXWDHeader+1), "Xvfb %s:%s.%d", hostname, display,
+ pScreen->myNum);
+
+ /* write colormap pixel slot values */
+
+ for (i = 0; i < pvfb->ncolors; i++)
+ {
+ pvfb->pXWDCmap[i].pixel = i;
+ }
+
+ /* byte swap to most significant byte first */
+
+ if (needswap)
+ {
+ SwapLongs((CARD32 *)pXWDHeader, SIZEOF(XWDheader)/4);
+ for (i = 0; i < pvfb->ncolors; i++)
+ {
+ register char n;
+ swapl(&pvfb->pXWDCmap[i].pixel, n);
+ }
+ }
+}
+
+
+static Bool
+vfbCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
+{
+ return FALSE;
+}
+
+static void
+vfbCrossScreen (ScreenPtr pScreen, Bool entering)
+{
+}
+
+static Bool vfbRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
+ return TRUE;
+}
+
+static Bool vfbUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) {
+ return TRUE;
+}
+
+static void vfbSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+}
+
+static void vfbMoveCursor(ScreenPtr pScreen, int x, int y)
+{
+}
+
+static miPointerSpriteFuncRec vfbPointerSpriteFuncs = {
+ vfbRealizeCursor,
+ vfbUnrealizeCursor,
+ vfbSetCursor,
+ vfbMoveCursor
+};
+
+static miPointerScreenFuncRec vfbPointerCursorFuncs = {
+ vfbCursorOffScreen,
+ vfbCrossScreen,
+ miPointerWarpCursor
+};
+
+static Bool
+vfbCloseScreen(int index, ScreenPtr pScreen)
+{
+ vfbScreenInfoPtr pvfb = &vfbScreens[index];
+ int i;
+
+ pScreen->CloseScreen = pvfb->closeScreen;
+
+ /*
+ * XXX probably lots of stuff to clean. For now,
+ * clear InstalledMaps[] so that server reset works correctly.
+ */
+ for (i = 0; i < MAXSCREENS; i++)
+ InstalledMaps[i] = NULL;
+
+ return pScreen->CloseScreen(index, pScreen);
+}
+
+static Bool
+vfbScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
+{
+ vfbScreenInfoPtr pvfb = &vfbScreens[index];
+ int dpi = 100;
+ int ret;
+ char *pbits;
+
+ if (monitorResolution) dpi = monitorResolution;
+
+ pvfb->paddedBytesWidth = PixmapBytePad(pvfb->width, pvfb->depth);
+ pvfb->bitsPerPixel = vfbBitsPerPixel(pvfb->depth);
+ pvfb->paddedWidth = pvfb->paddedBytesWidth * 8 / pvfb->bitsPerPixel;
+ pbits = vfbAllocateFramebufferMemory(pvfb);
+ if (!pbits) return FALSE;
+ vncFbptr[index] = pbits;
+
+ defaultColorVisualClass
+ = (pvfb->bitsPerPixel > 8) ? TrueColor : PseudoColor;
+
+ ret = fbScreenInit(pScreen, pbits, pvfb->width, pvfb->height,
+ dpi, dpi, pvfb->paddedWidth, pvfb->bitsPerPixel);
+
+#ifdef RENDER
+ if (ret && Render)
+ fbPictureInit (pScreen, 0, 0);
+#endif
+
+ if (!ret) return FALSE;
+
+ /* miInitializeBackingStore(pScreen); */
+
+ /*
+ * Circumvent the backing store that was just initialised. This amounts
+ * to a truely bizarre way of initialising SaveDoomedAreas and friends.
+ */
+
+ pScreen->InstallColormap = vfbInstallColormap;
+ pScreen->UninstallColormap = vfbUninstallColormap;
+ pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
+
+ pScreen->SaveScreen = vfbSaveScreen;
+ pScreen->StoreColors = vfbStoreColors;
+
+ miPointerInitialize(pScreen, &vfbPointerSpriteFuncs, &vfbPointerCursorFuncs,
+ FALSE);
+
+ vfbWriteXWDFileHeader(pScreen);
+
+ pScreen->blackPixel = pvfb->blackPixel;
+ pScreen->whitePixel = pvfb->whitePixel;
+
+ if (!pvfb->pixelFormatDefined && pvfb->depth == 16) {
+ pvfb->pixelFormatDefined = TRUE;
+ pvfb->rgbNotBgr = TRUE;
+ pvfb->blueBits = pvfb->redBits = 5;
+ pvfb->greenBits = 6;
+ }
+
+ if (pvfb->pixelFormatDefined) {
+ VisualPtr vis = pScreen->visuals;
+ for (int i = 0; i < pScreen->numVisuals; i++) {
+ if (pvfb->rgbNotBgr) {
+ vis->offsetBlue = 0;
+ vis->blueMask = (1 << pvfb->blueBits) - 1;
+ vis->offsetGreen = pvfb->blueBits;
+ vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
+ vis->offsetRed = vis->offsetGreen + pvfb->greenBits;
+ vis->redMask = ((1 << pvfb->redBits) - 1) << vis->offsetRed;
+ } else {
+ vis->offsetRed = 0;
+ vis->redMask = (1 << pvfb->redBits) - 1;
+ vis->offsetGreen = pvfb->redBits;
+ vis->greenMask = ((1 << pvfb->greenBits) - 1) << vis->offsetGreen;
+ vis->offsetBlue = vis->offsetGreen + pvfb->greenBits;
+ vis->blueMask = ((1 << pvfb->blueBits) - 1) << vis->offsetBlue;
+ }
+ vis++;
+ }
+ }
+
+ ret = fbCreateDefColormap(pScreen);
+
+ miSetZeroLineBias(pScreen, pvfb->lineBias);
+
+ pvfb->closeScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = vfbCloseScreen;
+
+#ifndef NO_INIT_BACKING_STORE
+ miInitializeBackingStore(pScreen);
+ pScreen->backingStoreSupport = Always;
+#endif
+
+ return ret;
+
+} /* end vfbScreenInit */
+
+
+static void vfbClientStateChange(CallbackListPtr*, pointer, pointer) {
+ dispatchException &= ~DE_RESET;
+}
+
+void
+InitOutput(ScreenInfo *screenInfo, int argc, char **argv)
+{
+ ErrorF("\nXvnc %s - built %s\n%s", XVNCVERSION, buildtime, XVNCCOPYRIGHT);
+ ErrorF("Underlying X server release %d, %s\n\n", VENDOR_RELEASE,
+ VENDOR_STRING);
+ int i;
+ int NumFormats = 0;
+
+ /* initialize pixmap formats */
+
+ /* must have a pixmap depth to match every screen depth */
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+ vfbPixmapDepths[vfbScreens[i].depth] = TRUE;
+ }
+
+ /* RENDER needs a good set of pixmaps. */
+ if (Render) {
+ vfbPixmapDepths[1] = TRUE;
+ vfbPixmapDepths[4] = TRUE;
+ vfbPixmapDepths[8] = TRUE;
+/* vfbPixmapDepths[15] = TRUE; */
+ vfbPixmapDepths[16] = TRUE;
+ vfbPixmapDepths[24] = TRUE;
+ vfbPixmapDepths[32] = TRUE;
+ }
+
+ for (i = 1; i <= 32; i++)
+ {
+ if (vfbPixmapDepths[i])
+ {
+ if (NumFormats >= MAXFORMATS)
+ FatalError ("MAXFORMATS is too small for this server\n");
+ screenInfo->formats[NumFormats].depth = i;
+ screenInfo->formats[NumFormats].bitsPerPixel = vfbBitsPerPixel(i);
+ screenInfo->formats[NumFormats].scanlinePad = BITMAP_SCANLINE_PAD;
+ NumFormats++;
+ }
+ }
+
+ screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
+ screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
+ screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
+ screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
+ screenInfo->numPixmapFormats = NumFormats;
+
+ /* initialize screens */
+
+ for (i = 0; i < vfbNumScreens; i++)
+ {
+ if (-1 == AddScreen(vfbScreenInit, argc, argv))
+ {
+ FatalError("Couldn't add screen %d", i);
+ }
+ }
+
+ if (!AddCallback(&ClientStateCallback, vfbClientStateChange, 0)) {
+ FatalError("AddCallback failed\n");
+ }
+} /* end InitOutput */
+
+#ifdef DPMSExtension
+extern "C" {
+#if NeedFunctionPrototypes
+ void DPMSSet(CARD16 level)
+#else
+ void DPMSSet(level)
+ CARD16 level;
+#endif
+ {
+ return;
+ }
+
+ Bool DPMSSupported()
+ {
+ return FALSE;
+ }
+}
+#endif
+
+/* this is just to get the server to link on AIX */
+#ifdef AIXV3
+int SelectWaitTime = 10000; /* usec */
+#endif
+
+Bool LegalModifier(unsigned int key, DevicePtr pDev)
+{
+ return TRUE;
+}
+
+void ProcessInputEvents()
+{
+ mieqProcessInputEvents();
+ miPointerUpdate();
+}
+
+/* Fairly standard US PC Keyboard */
+
+#define VFB_MIN_KEY 8
+#define VFB_MAX_KEY 255
+#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1)
+#define KEYSYMS_PER_KEY 2
+KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = {
+ NoSymbol, NoSymbol,
+ XK_Escape, NoSymbol,
+ XK_1, XK_exclam,
+ XK_2, XK_at,
+ XK_3, XK_numbersign,
+ XK_4, XK_dollar,
+ XK_5, XK_percent,
+ XK_6, XK_asciicircum,
+ XK_7, XK_ampersand,
+ XK_8, XK_asterisk,
+ XK_9, XK_parenleft,
+ XK_0, XK_parenright,
+ XK_minus, XK_underscore,
+ XK_equal, XK_plus,
+ XK_BackSpace, NoSymbol,
+ XK_Tab, NoSymbol,
+ XK_q, XK_Q,
+ XK_w, XK_W,
+ XK_e, XK_E,
+ XK_r, XK_R,
+ XK_t, XK_T,
+ XK_y, XK_Y,
+ XK_u, XK_U,
+ XK_i, XK_I,
+ XK_o, XK_O,
+ XK_p, XK_P,
+ XK_bracketleft, XK_braceleft,
+ XK_bracketright, XK_braceright,
+ XK_Return, NoSymbol,
+ XK_Control_L, NoSymbol,
+ XK_a, XK_A,
+ XK_s, XK_S,
+ XK_d, XK_D,
+ XK_f, XK_F,
+ XK_g, XK_G,
+ XK_h, XK_H,
+ XK_j, XK_J,
+ XK_k, XK_K,
+ XK_l, XK_L,
+ XK_semicolon, XK_colon,
+ XK_apostrophe, XK_quotedbl,
+ XK_grave, XK_asciitilde,
+ XK_Shift_L, NoSymbol,
+ XK_backslash, XK_bar,
+ XK_z, XK_Z,
+ XK_x, XK_X,
+ XK_c, XK_C,
+ XK_v, XK_V,
+ XK_b, XK_B,
+ XK_n, XK_N,
+ XK_m, XK_M,
+ XK_comma, XK_less,
+ XK_period, XK_greater,
+ XK_slash, XK_question,
+ XK_Shift_R, NoSymbol,
+ XK_KP_Multiply, NoSymbol,
+ XK_Alt_L, XK_Meta_L,
+ XK_space, NoSymbol,
+ /*XK_Caps_Lock*/ NoSymbol, NoSymbol,
+ XK_F1, NoSymbol,
+ XK_F2, NoSymbol,
+ XK_F3, NoSymbol,
+ XK_F4, NoSymbol,
+ XK_F5, NoSymbol,
+ XK_F6, NoSymbol,
+ XK_F7, NoSymbol,
+ XK_F8, NoSymbol,
+ XK_F9, NoSymbol,
+ XK_F10, NoSymbol,
+ XK_Num_Lock, XK_Pointer_EnableKeys,
+ XK_Scroll_Lock, NoSymbol,
+ XK_KP_Home, XK_KP_7,
+ XK_KP_Up, XK_KP_8,
+ XK_KP_Prior, XK_KP_9,
+ XK_KP_Subtract, NoSymbol,
+ XK_KP_Left, XK_KP_4,
+ XK_KP_Begin, XK_KP_5,
+ XK_KP_Right, XK_KP_6,
+ XK_KP_Add, NoSymbol,
+ XK_KP_End, XK_KP_1,
+ XK_KP_Down, XK_KP_2,
+ XK_KP_Next, XK_KP_3,
+ XK_KP_Insert, XK_KP_0,
+ XK_KP_Delete, XK_KP_Decimal,
+ NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol,
+ NoSymbol, NoSymbol,
+ XK_F11, NoSymbol,
+ XK_F12, NoSymbol,
+ XK_Home, NoSymbol,
+ XK_Up, NoSymbol,
+ XK_Prior, NoSymbol,
+ XK_Left, NoSymbol,
+ NoSymbol, NoSymbol,
+ XK_Right, NoSymbol,
+ XK_End, NoSymbol,
+ XK_Down, NoSymbol,
+ XK_Next, NoSymbol,
+ XK_Insert, NoSymbol,
+ XK_Delete, NoSymbol,
+ XK_KP_Enter, NoSymbol,
+ XK_Control_R, NoSymbol,
+ XK_Pause, XK_Break,
+ XK_Print, XK_Execute,
+ XK_KP_Divide, NoSymbol,
+ XK_Alt_R, XK_Meta_R,
+};
+
+static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ int i;
+
+ for (i = 0; i < MAP_LENGTH; i++)
+ pModMap[i] = NoSymbol;
+
+ for (i = 0; i < VFB_MAP_LEN; i++) {
+ if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock)
+ pModMap[i + VFB_MIN_KEY] = LockMask;
+ else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L ||
+ keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R)
+ pModMap[i + VFB_MIN_KEY] = ShiftMask;
+ else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L ||
+ keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) {
+ pModMap[i + VFB_MIN_KEY] = ControlMask;
+ }
+ else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L ||
+ keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R)
+ pModMap[i + VFB_MIN_KEY] = Mod1Mask;
+ }
+
+ pKeySyms->minKeyCode = VFB_MIN_KEY;
+ pKeySyms->maxKeyCode = VFB_MAX_KEY;
+ pKeySyms->mapWidth = KEYSYMS_PER_KEY;
+ pKeySyms->map = keyboardMap;
+
+ return TRUE;
+}
+
+static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_)
+{
+ if (percent > 0)
+ vncBell();
+}
+
+static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+ KeySymsRec keySyms;
+ CARD8 modMap[MAP_LENGTH];
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ GetMappings(&keySyms, modMap);
+ InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
+ (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA);
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ break;
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ break;
+ case DEVICE_CLOSE:
+ break;
+ }
+ return Success;
+}
+
+static int vfbMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+ BYTE map[6];
+ DevicePtr pDev = (DevicePtr)pDevice;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ map[1] = 1;
+ map[2] = 2;
+ map[3] = 3;
+ map[4] = 4;
+ map[5] = 5;
+ InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
+ (PtrCtrlProcPtr)NoopDDA, miPointerGetMotionBufferSize());
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ break;
+
+ case DEVICE_OFF:
+ pDev->on = FALSE;
+ break;
+
+ case DEVICE_CLOSE:
+ break;
+ }
+ return Success;
+}
+
+// InitInput is called after InitExtensions, so we're guaranteed that
+// vncExtensionInit() has already been called.
+
+void InitInput(int argc, char *argv[])
+{
+ DeviceIntPtr p, k;
+ p = AddInputDevice(vfbMouseProc, TRUE);
+ k = AddInputDevice(vfbKeybdProc, TRUE);
+ RegisterPointerDevice(p);
+ RegisterKeyboardDevice(k);
+ miRegisterPointerDevice(screenInfo.screens[0], p);
+ (void)mieqInit ((DevicePtr)k, (DevicePtr)p);
+}