Merge branch 'x0-xdesktop-initial-cursor' of https://github.com/x11clone/x11clone
diff --git a/README.txt b/README.txt
index 46dac3a..167a940 100644
--- a/README.txt
+++ b/README.txt
@@ -34,6 +34,7 @@
Copyright (C) 2009-2011 D. R. Commander
Copyright (C) 2009-2011 Pierre Ossman for Cendio AB
Copyright (C) 2004, 2009-2011 Red Hat, Inc.
+ Copyright (C) 2017 Peter Astrand for Cendio AB
Copyright (C) 2009-2017 TigerVNC Team
All Rights Reserved.
diff --git a/common/network/Socket.h b/common/network/Socket.h
index 874a59c..7a30cac 100644
--- a/common/network/Socket.h
+++ b/common/network/Socket.h
@@ -50,6 +50,7 @@
// if shutdown() is overridden then the override MUST call on to here
virtual void shutdown() {isShutdown_ = true;}
bool isShutdown() const {return isShutdown_;}
+ virtual bool cork(bool enable) = 0;
// information about this end of the socket
virtual int getMyPort() = 0;
diff --git a/common/network/TcpSocket.cxx b/common/network/TcpSocket.cxx
index cf03c10..9603c38 100644
--- a/common/network/TcpSocket.cxx
+++ b/common/network/TcpSocket.cxx
@@ -349,12 +349,12 @@
return true;
}
-bool TcpSocket::cork(int sock, bool enable) {
+bool TcpSocket::cork(bool enable) {
#ifndef TCP_CORK
return false;
#else
int one = enable ? 1 : 0;
- if (setsockopt(sock, IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one)) < 0)
+ if (setsockopt(getFd(), IPPROTO_TCP, TCP_CORK, (char *)&one, sizeof(one)) < 0)
return false;
return true;
#endif
diff --git a/common/network/TcpSocket.h b/common/network/TcpSocket.h
index a97e683..c1b142f 100644
--- a/common/network/TcpSocket.h
+++ b/common/network/TcpSocket.h
@@ -62,9 +62,9 @@
virtual bool sameMachine();
virtual void shutdown();
+ virtual bool cork(bool enable);
static bool enableNagles(int sock, bool enable);
- static bool cork(int sock, bool enable);
static bool isListening(int sock);
static int getSockPort(int sock);
private:
diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx
index 29e864f..8fe9df9 100644
--- a/common/rdr/FdOutStream.cxx
+++ b/common/rdr/FdOutStream.cxx
@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2011 Pierre Ossman for Cendio AB
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
+#include <sys/socket.h>
#endif
/* Old systems have select() in sys/time.h */
@@ -193,7 +195,14 @@
return 0;
do {
- n = ::write(fd, data, length);
+ // select only guarantees that you can write SO_SNDLOWAT without
+ // blocking, which is normally 1. Use MSG_DONTWAIT to avoid
+ // blocking, when possible.
+#ifndef MSG_DONTWAIT
+ n = ::send(fd, (const char*)data, length, 0);
+#else
+ n = ::send(fd, (const char*)data, length, MSG_DONTWAIT);
+#endif
} while (n < 0 && (errno == EINTR));
if (n < 0)
diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx
index a5c2302..418a0c9 100644
--- a/common/rfb/Configuration.cxx
+++ b/common/rfb/Configuration.cxx
@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2004-2005 Cendio AB.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -166,6 +167,23 @@
}
+bool Configuration::remove(const char* param) {
+ VoidParameter *current = head;
+ VoidParameter **prevnext = &head;
+
+ while (current) {
+ if (strcasecmp(current->getName(), param) == 0) {
+ *prevnext = current->_next;
+ return true;
+ }
+ prevnext = ¤t->_next;
+ current = current->_next;
+ }
+
+ return false;
+}
+
+
// -=- VoidParameter
VoidParameter::VoidParameter(const char* name_, const char* desc_,
diff --git a/common/rfb/Configuration.h b/common/rfb/Configuration.h
index d319915..6197317 100644
--- a/common/rfb/Configuration.h
+++ b/common/rfb/Configuration.h
@@ -80,6 +80,9 @@
// - List the parameters of this Configuration group
void list(int width=79, int nameWidth=10);
+ // - Remove a parameter from this Configuration group
+ bool remove(const char* param);
+
// - readFromFile
// Read configuration parameters from the specified file.
void readFromFile(const char* filename);
@@ -116,6 +119,9 @@
static void listParams(int width=79, int nameWidth=10) {
global()->list(width, nameWidth);
}
+ static bool removeParam(const char* param) {
+ return global()->remove(param);
+ }
private:
friend class VoidParameter;
diff --git a/common/rfb/Timer.cxx b/common/rfb/Timer.cxx
index efae36e..71887a0 100644
--- a/common/rfb/Timer.cxx
+++ b/common/rfb/Timer.cxx
@@ -26,11 +26,6 @@
#include <rfb/util.h>
#include <rfb/LogWriter.h>
-// XXX Lynx/OS 2.3: proto for gettimeofday()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
using namespace rfb;
#ifndef __NO_DEFINE_VLOG__
diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx
index 9e58657..0e97a78 100644
--- a/common/rfb/VNCSConnectionST.cxx
+++ b/common/rfb/VNCSConnectionST.cxx
@@ -168,7 +168,7 @@
// Get the underlying TCP layer to build large packets if we send
// multiple small responses.
- network::TcpSocket::cork(sock->getFd(), true);
+ sock->cork(true);
while (getInStream()->checkNoWait(1)) {
if (pendingSyncFence) {
@@ -185,7 +185,7 @@
}
// Flush out everything in case we go idle after this.
- network::TcpSocket::cork(sock->getFd(), false);
+ sock->cork(false);
inProcessMessages = false;
@@ -1094,7 +1094,7 @@
// mode, we will also have small fence messages around the update. We
// need to aggregate these in order to not clog up TCP's congestion
// window.
- network::TcpSocket::cork(sock->getFd(), true);
+ sock->cork(true);
// First take care of any updates that cannot contain framebuffer data
// changes.
@@ -1103,7 +1103,7 @@
// Then real data (if possible)
writeDataUpdate();
- network::TcpSocket::cork(sock->getFd(), false);
+ sock->cork(false);
}
void VNCSConnectionST::writeNoDataUpdate()
diff --git a/unix/tx/TXDialog.h b/unix/tx/TXDialog.h
index 7a52f92..28876e7 100644
--- a/unix/tx/TXDialog.h
+++ b/unix/tx/TXDialog.h
@@ -31,11 +31,6 @@
#include "TXWindow.h"
#include <errno.h>
-// XXX Lynx/OS 2.3: protos for bzero(), select()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
class TXDialog : public TXWindow, public TXDeleteWindowCallback {
public:
TXDialog(Display* dpy, int width, int height, const char* name,
diff --git a/unix/x0vncserver/CMakeLists.txt b/unix/x0vncserver/CMakeLists.txt
index 5831c4d..5930e32 100644
--- a/unix/x0vncserver/CMakeLists.txt
+++ b/unix/x0vncserver/CMakeLists.txt
@@ -14,6 +14,7 @@
qnum_to_xorgkbd.c
x0vncserver.cxx
XPixelBuffer.cxx
+ XDesktop.cxx
../vncconfig/QueryConnectDialog.cxx
)
diff --git a/unix/x0vncserver/Geometry.cxx b/unix/x0vncserver/Geometry.cxx
index adc72c3..48c1842 100644
--- a/unix/x0vncserver/Geometry.cxx
+++ b/unix/x0vncserver/Geometry.cxx
@@ -23,6 +23,8 @@
#include <rfb/LogWriter.h>
#include <x0vncserver/Geometry.h>
+using namespace rfb;
+
static LogWriter vlog("Geometry");
StringParameter Geometry::m_geometryParam("Geometry",
diff --git a/unix/x0vncserver/Geometry.h b/unix/x0vncserver/Geometry.h
index 9caeeba..98bafb2 100644
--- a/unix/x0vncserver/Geometry.h
+++ b/unix/x0vncserver/Geometry.h
@@ -26,8 +26,6 @@
#include <rfb/Rect.h>
#include <rfb/Configuration.h>
-using namespace rfb;
-
class Geometry
{
public:
@@ -43,18 +41,18 @@
int offsetTop() const { return m_rect.tl.y; }
// Return the same information as a Rect structure.
- const Rect& getRect() const { return m_rect; }
+ const rfb::Rect& getRect() const { return m_rect; }
protected:
// Parse a string, extract size and coordinates,
// and return that rectangle clipped to m_rect.
- Rect parseString(const char *arg) const;
+ rfb::Rect parseString(const char *arg) const;
- static StringParameter m_geometryParam;
+ static rfb::StringParameter m_geometryParam;
int m_fullWidth;
int m_fullHeight;
- Rect m_rect;
+ rfb::Rect m_rect;
};
#endif // __GEOMETRY_H__
diff --git a/unix/x0vncserver/Image.cxx b/unix/x0vncserver/Image.cxx
index f998c6a..ca3d642 100644
--- a/unix/x0vncserver/Image.cxx
+++ b/unix/x0vncserver/Image.cxx
@@ -24,10 +24,8 @@
#include <stdlib.h>
#include <sys/types.h>
-#ifdef HAVE_MITSHM
#include <sys/ipc.h>
#include <sys/shm.h>
-#endif
#include <rfb/LogWriter.h>
#include <x0vncserver/Image.h>
@@ -196,8 +194,6 @@
updateRect(src->xim, dst_x, dst_y, src_x, src_y, w, h);
}
-#ifdef HAVE_MITSHM
-
//
// ShmImage class implementation.
//
@@ -323,182 +319,14 @@
XGetSubImage(dpy, wnd, x, y, w, h, AllPlanes, ZPixmap, xim, dst_x, dst_y);
}
-#ifdef HAVE_READDISPLAY
-
-//
-// IrixOverlayShmImage class implementation.
-//
-
-IrixOverlayShmImage::IrixOverlayShmImage(Display *d)
- : ShmImage(d), readDisplayBuf(NULL)
-{
-}
-
-IrixOverlayShmImage::IrixOverlayShmImage(Display *d, int width, int height)
- : ShmImage(d), readDisplayBuf(NULL)
-{
- Init(width, height);
-}
-
-void IrixOverlayShmImage::Init(int width, int height)
-{
- // First determine the pixel format used by XReadDisplay.
- XVisualInfo vinfo;
- if (!getOverlayVisualInfo(&vinfo))
- return;
-
- // Create an SHM image of the same format.
- ShmImage::Init(width, height, &vinfo);
- if (xim == NULL)
- return;
-
- // FIXME: Check if the extension is available at run time.
- readDisplayBuf = XShmCreateReadDisplayBuf(dpy, NULL, shminfo, width, height);
-}
-
-bool IrixOverlayShmImage::getOverlayVisualInfo(XVisualInfo *vinfo_ret)
-{
- // First, get an image in the format returned by XReadDisplay.
- unsigned long hints = 0, hints_ret;
- XImage *testImage = XReadDisplay(dpy, DefaultRootWindow(dpy),
- 0, 0, 8, 8, hints, &hints_ret);
- if (testImage == NULL)
- return false;
-
- // Fill in a template for matching visuals.
- XVisualInfo tmpl;
- tmpl.c_class = TrueColor;
- tmpl.depth = 24;
- tmpl.red_mask = testImage->red_mask;
- tmpl.green_mask = testImage->green_mask;
- tmpl.blue_mask = testImage->blue_mask;
-
- // List fields in template that make sense.
- long mask = (VisualClassMask |
- VisualRedMaskMask |
- VisualGreenMaskMask |
- VisualBlueMaskMask);
-
- // We don't need that image any more.
- XDestroyImage(testImage);
-
- // Now, get a list of matching visuals available.
- int nVisuals;
- XVisualInfo *vinfo = XGetVisualInfo(dpy, mask, &tmpl, &nVisuals);
- if (vinfo == NULL || nVisuals <= 0) {
- if (vinfo != NULL) {
- XFree(vinfo);
- }
- return false;
- }
-
- // Use first visual from the list.
- *vinfo_ret = vinfo[0];
-
- XFree(vinfo);
-
- return true;
-}
-
-IrixOverlayShmImage::~IrixOverlayShmImage()
-{
- if (readDisplayBuf != NULL)
- XShmDestroyReadDisplayBuf(readDisplayBuf);
-}
-
-void IrixOverlayShmImage::get(Window wnd, int x, int y)
-{
- get(wnd, x, y, xim->width, xim->height);
-}
-
-void IrixOverlayShmImage::get(Window wnd, int x, int y, int w, int h,
- int dst_x, int dst_y)
-{
- XRectangle rect;
- unsigned long hints = XRD_TRANSPARENT | XRD_READ_POINTER;
-
- rect.x = x;
- rect.y = y;
- rect.width = w;
- rect.height = h;
-
- XShmReadDisplayRects(dpy, wnd,
- &rect, 1, readDisplayBuf,
- dst_x - x, dst_y - y,
- hints, &hints);
-}
-
-#endif // HAVE_READDISPLAY
-#endif // HAVE_MITSHM
-
-#ifdef HAVE_SUN_OVL
-
-//
-// SolarisOverlayImage class implementation
-//
-
-SolarisOverlayImage::SolarisOverlayImage(Display *d)
- : Image(d)
-{
-}
-
-SolarisOverlayImage::SolarisOverlayImage(Display *d, int width, int height)
- : Image(d)
-{
- Init(width, height);
-}
-
-void SolarisOverlayImage::Init(int width, int height)
-{
- // FIXME: Check if the extension is available at run time.
- // FIXME: Maybe just read a small (e.g. 8x8) screen area then
- // reallocate xim->data[] and correct width and height?
- xim = XReadScreen(dpy, DefaultRootWindow(dpy), 0, 0, width, height, True);
- if (xim == NULL) {
- vlog.error("XReadScreen() failed");
- return;
- }
-}
-
-SolarisOverlayImage::~SolarisOverlayImage()
-{
-}
-
-void SolarisOverlayImage::get(Window wnd, int x, int y)
-{
- get(wnd, x, y, xim->width, xim->height);
-}
-
-void SolarisOverlayImage::get(Window wnd, int x, int y, int w, int h,
- int dst_x, int dst_y)
-{
- XImage *tmp_xim = XReadScreen(dpy, wnd, x, y, w, h, True);
- if (tmp_xim == NULL)
- return;
-
- updateRect(tmp_xim, dst_x, dst_y);
-
- XDestroyImage(tmp_xim);
-}
-
-#endif // HAVE_SUN_OVL
-
//
// ImageFactory class implementation
//
// FIXME: Make ImageFactory always create images of the same class?
//
-// Prepare useful shortcuts for compile-time options.
-#if defined(HAVE_READDISPLAY) && defined(HAVE_MITSHM)
-#define HAVE_SHM_READDISPLAY
-#endif
-#if defined(HAVE_SHM_READDISPLAY) || defined(HAVE_SUN_OVL)
-#define HAVE_OVERLAY_EXT
-#endif
-
-ImageFactory::ImageFactory(bool allowShm, bool allowOverlay)
- : mayUseShm(allowShm), mayUseOverlay(allowOverlay)
+ImageFactory::ImageFactory(bool allowShm)
+ : mayUseShm(allowShm)
{
}
@@ -510,33 +338,8 @@
{
Image *image = NULL;
- // First, try to create an image with overlay support.
-
-#ifdef HAVE_OVERLAY_EXT
- if (mayUseOverlay) {
-#if defined(HAVE_SHM_READDISPLAY)
- if (mayUseShm) {
- image = new IrixOverlayShmImage(d, width, height);
- if (image->xim != NULL) {
- return image;
- }
- }
-#elif defined(HAVE_SUN_OVL)
- image = new SolarisOverlayImage(d, width, height);
- if (image->xim != NULL) {
- return image;
- }
-#endif
- if (image != NULL) {
- delete image;
- vlog.error("Failed to create overlay image, trying other options");
- }
- }
-#endif // HAVE_OVERLAY_EXT
-
// Now, try to use shared memory image.
-#ifdef HAVE_MITSHM
if (mayUseShm) {
image = new ShmImage(d, width, height);
if (image->xim != NULL) {
@@ -546,7 +349,6 @@
delete image;
vlog.error("Failed to create SHM image, falling back to Xlib image");
}
-#endif // HAVE_MITSHM
// Fall back to Xlib image.
diff --git a/unix/x0vncserver/Image.h b/unix/x0vncserver/Image.h
index 4cac8b4..23502eb 100644
--- a/unix/x0vncserver/Image.h
+++ b/unix/x0vncserver/Image.h
@@ -92,8 +92,6 @@
// ShmImage uses MIT-SHM extension of an X server to get image data.
//
-#ifdef HAVE_MITSHM
-
#include <X11/extensions/XShm.h>
class ShmImage : public Image {
@@ -124,89 +122,6 @@
};
//
-// IrixOverlayShmImage uses ReadDisplay extension of an X server to
-// get truecolor image data, regardless of the default X visual type.
-// This method is available on Irix only.
-//
-
-#ifdef HAVE_READDISPLAY
-
-#include <X11/extensions/readdisplay.h>
-
-class IrixOverlayShmImage : public ShmImage {
-
-public:
-
- IrixOverlayShmImage(Display *d);
- IrixOverlayShmImage(Display *d, int width, int height);
- virtual ~IrixOverlayShmImage();
-
- virtual const char *className() const {
- return "IrixOverlayShmImage";
- }
- virtual const char *classDesc() const {
- return "IRIX-specific SHM-aware overlay image";
- }
-
- virtual void get(Window wnd, int x = 0, int y = 0);
- virtual void get(Window wnd, int x, int y, int w, int h,
- int dst_x = 0, int dst_y = 0);
-
-protected:
-
- void Init(int width, int height);
-
- // This method searches available X visuals for one that matches
- // actual pixel format returned by XReadDisplay(). Returns true on
- // success, false if there is no matching visual. On success, visual
- // information is placed into the structure pointed by vinfo_ret.
- bool getOverlayVisualInfo(XVisualInfo *vinfo_ret);
-
- ShmReadDisplayBuf *readDisplayBuf;
-
-};
-
-#endif // HAVE_READDISPLAY
-#endif // HAVE_MITSHM
-
-//
-// SolarisOverlayImage uses SUN_OVL extension of an X server to get
-// truecolor image data, regardless of the default X visual type. This
-// method is available on Solaris only.
-//
-
-#ifdef HAVE_SUN_OVL
-
-#include <X11/extensions/transovl.h>
-
-class SolarisOverlayImage : public Image {
-
-public:
-
- SolarisOverlayImage(Display *d);
- SolarisOverlayImage(Display *d, int width, int height);
- virtual ~SolarisOverlayImage();
-
- virtual const char *className() const {
- return "SolarisOverlayImage";
- }
- virtual const char *classDesc() const {
- return "Solaris-specific non-SHM overlay image";
- }
-
- virtual void get(Window wnd, int x = 0, int y = 0);
- virtual void get(Window wnd, int x, int y, int w, int h,
- int dst_x = 0, int dst_y = 0);
-
-protected:
-
- void Init(int width, int height);
-
-};
-
-#endif // HAVE_SUN_OVL
-
-//
// ImageFactory class is used to produce instances of Image-derived
// objects that are most appropriate for current X server and user
// settings.
@@ -216,18 +131,16 @@
public:
- ImageFactory(bool allowShm, bool allowOverlay);
+ ImageFactory(bool allowShm);
virtual ~ImageFactory();
bool isShmAllowed() { return mayUseShm; }
- bool isOverlayAllowed() { return mayUseOverlay; }
virtual Image *newImage(Display *d, int width, int height);
protected:
bool mayUseShm;
- bool mayUseOverlay;
};
diff --git a/unix/x0vncserver/PollingManager.cxx b/unix/x0vncserver/PollingManager.cxx
index 3a040e2..d7f6f46 100644
--- a/unix/x0vncserver/PollingManager.cxx
+++ b/unix/x0vncserver/PollingManager.cxx
@@ -31,6 +31,8 @@
#include <x0vncserver/PollingManager.h>
+using namespace rfb;
+
static LogWriter vlog("PollingMgr");
const int PollingManager::m_pollingOrder[32] = {
diff --git a/unix/x0vncserver/PollingManager.h b/unix/x0vncserver/PollingManager.h
index e106f79..5025fa5 100644
--- a/unix/x0vncserver/PollingManager.h
+++ b/unix/x0vncserver/PollingManager.h
@@ -32,8 +32,6 @@
#include <x0vncserver/TimeMillis.h>
#endif
-using namespace rfb;
-
class PollingManager {
public:
@@ -42,12 +40,12 @@
int offsetLeft = 0, int offsetTop = 0);
virtual ~PollingManager();
- void poll(VNCServer *server);
+ void poll(rfb::VNCServer *server);
protected:
// Screen polling. Returns true if some changes were detected.
- bool pollScreen(VNCServer *server);
+ bool pollScreen(rfb::VNCServer *server);
Display *m_dpy;
@@ -85,7 +83,7 @@
int checkRow(int x, int y, int w);
int checkColumn(int x, int y, int h, bool *pChangeFlags);
- int sendChanges(VNCServer *server) const;
+ int sendChanges(rfb::VNCServer *server) const;
// Check neighboring tiles and update m_changeFlags[].
void checkNeighbors();
diff --git a/unix/x0vncserver/TimeMillis.cxx b/unix/x0vncserver/TimeMillis.cxx
index 059c043..b5054c9 100644
--- a/unix/x0vncserver/TimeMillis.cxx
+++ b/unix/x0vncserver/TimeMillis.cxx
@@ -22,11 +22,6 @@
#include <x0vncserver/TimeMillis.h>
-// XXX Lynx/OS 2.3: get proto for gettimeofday()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
TimeMillis::TimeMillis()
{
update();
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
new file mode 100644
index 0000000..07b3a9c
--- /dev/null
+++ b/unix/x0vncserver/XDesktop.cxx
@@ -0,0 +1,427 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2004-2008 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
+ *
+ * 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 <x0vncserver/XDesktop.h>
+
+#include <X11/XKBlib.h>
+#ifdef HAVE_XTEST
+#include <X11/extensions/XTest.h>
+#endif
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+#endif
+
+#include <x0vncserver/Geometry.h>
+#include <x0vncserver/XPixelBuffer.h>
+
+using namespace rfb;
+
+extern const unsigned short code_map_qnum_to_xorgevdev[];
+extern const unsigned int code_map_qnum_to_xorgevdev_len;
+
+extern const unsigned short code_map_qnum_to_xorgkbd[];
+extern const unsigned int code_map_qnum_to_xorgkbd_len;
+
+extern rfb::BoolParameter useShm;
+extern rfb::BoolParameter rawKeyboard;
+
+static rfb::LogWriter vlog("XDesktop");
+
+// order is important as it must match RFB extension
+static const char * ledNames[XDESKTOP_N_LEDS] = {
+ "Scroll Lock", "Num Lock", "Caps Lock"
+};
+
+XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
+ : dpy(dpy_), geometry(geometry_), pb(0), server(0),
+ oldButtonMask(0), haveXtest(false), haveDamage(false),
+ maxButtons(0), running(false), ledMasks(), ledState(0),
+ codeMap(0), codeMapLen(0)
+{
+ int major, minor;
+
+ int xkbOpcode, xkbErrorBase;
+
+ major = XkbMajorVersion;
+ minor = XkbMinorVersion;
+ if (!XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase,
+ &xkbErrorBase, &major, &minor)) {
+ vlog.error("XKEYBOARD extension not present");
+ throw Exception();
+ }
+
+ XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask,
+ XkbIndicatorStateNotifyMask);
+
+ // figure out bit masks for the indicators we are interested in
+ for (int i = 0; i < XDESKTOP_N_LEDS; i++) {
+ Atom a;
+ int shift;
+ Bool on;
+
+ a = XInternAtom(dpy, ledNames[i], True);
+ if (!a || !XkbGetNamedIndicator(dpy, a, &shift, &on, NULL, NULL))
+ continue;
+
+ ledMasks[i] = 1u << shift;
+ vlog.debug("Mask for '%s' is 0x%x", ledNames[i], ledMasks[i]);
+ if (on)
+ ledState |= 1u << i;
+ }
+
+ // X11 unfortunately uses keyboard driver specific keycodes and provides no
+ // direct way to query this, so guess based on the keyboard mapping
+ XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+ if (desc && desc->names) {
+ char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
+
+ if (keycodes) {
+ if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
+ codeMap = code_map_qnum_to_xorgevdev;
+ codeMapLen = code_map_qnum_to_xorgevdev_len;
+ vlog.info("Using evdev codemap\n");
+ } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
+ codeMap = code_map_qnum_to_xorgkbd;
+ codeMapLen = code_map_qnum_to_xorgkbd_len;
+ vlog.info("Using xorgkbd codemap\n");
+ } else {
+ vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
+ }
+ XFree(keycodes);
+ } else {
+ vlog.debug("Unable to get keycode map\n");
+ }
+
+ XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
+ }
+
+#ifdef HAVE_XTEST
+ int xtestEventBase;
+ int xtestErrorBase;
+
+ if (XTestQueryExtension(dpy, &xtestEventBase,
+ &xtestErrorBase, &major, &minor)) {
+ XTestGrabControl(dpy, True);
+ vlog.info("XTest extension present - version %d.%d",major,minor);
+ haveXtest = true;
+ } else {
+#endif
+ vlog.info("XTest extension not present");
+ vlog.info("Unable to inject events or display while server is grabbed");
+#ifdef HAVE_XTEST
+ }
+#endif
+
+#ifdef HAVE_XDAMAGE
+ int xdamageErrorBase;
+
+ if (XDamageQueryExtension(dpy, &xdamageEventBase, &xdamageErrorBase)) {
+ haveDamage = true;
+ } else {
+#endif
+ vlog.info("DAMAGE extension not present");
+ vlog.info("Will have to poll screen for changes");
+#ifdef HAVE_XDAMAGE
+ }
+#endif
+
+#ifdef HAVE_XFIXES
+ int xfixesErrorBase;
+
+ if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
+ XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
+ XFixesDisplayCursorNotifyMask);
+ } else {
+#endif
+ vlog.info("XFIXES extension not present");
+ vlog.info("Will not be able to display cursors");
+#ifdef HAVE_XFIXES
+ }
+#endif
+
+ TXWindow::setGlobalEventHandler(this);
+}
+
+XDesktop::~XDesktop() {
+ stop();
+}
+
+
+void XDesktop::poll() {
+ if (pb and not haveDamage)
+ pb->poll(server);
+ if (running) {
+ Window root, child;
+ int x, y, wx, wy;
+ unsigned int mask;
+ XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
+ &x, &y, &wx, &wy, &mask);
+ server->setCursorPos(rfb::Point(x, y));
+ }
+ }
+
+
+void XDesktop::start(VNCServer* vs) {
+
+ // Determine actual number of buttons of the X pointer device.
+ unsigned char btnMap[8];
+ int numButtons = XGetPointerMapping(dpy, btnMap, 8);
+ maxButtons = (numButtons > 8) ? 8 : numButtons;
+ vlog.info("Enabling %d button%s of X pointer device",
+ maxButtons, (maxButtons != 1) ? "s" : "");
+
+ // Create an ImageFactory instance for producing Image objects.
+ ImageFactory factory((bool)useShm);
+
+ // Create pixel buffer and provide it to the server object.
+ pb = new XPixelBuffer(dpy, factory, geometry->getRect());
+ vlog.info("Allocated %s", pb->getImage()->classDesc());
+
+ server = (VNCServerST *)vs;
+ server->setPixelBuffer(pb);
+
+#ifdef HAVE_XDAMAGE
+ if (haveDamage) {
+ damage = XDamageCreate(dpy, DefaultRootWindow(dpy),
+ XDamageReportRawRectangles);
+ }
+#endif
+
+#ifdef HAVE_XFIXES
+ setCursor();
+#endif
+
+ server->setLEDState(ledState);
+
+ running = true;
+}
+
+void XDesktop::stop() {
+ running = false;
+
+#ifdef HAVE_XDAMAGE
+ if (haveDamage)
+ XDamageDestroy(dpy, damage);
+#endif
+
+ delete pb;
+ pb = 0;
+}
+
+bool XDesktop::isRunning() {
+ return running;
+}
+
+void XDesktop::pointerEvent(const Point& pos, int buttonMask) {
+#ifdef HAVE_XTEST
+ if (!haveXtest) return;
+ XTestFakeMotionEvent(dpy, DefaultScreen(dpy),
+ geometry->offsetLeft() + pos.x,
+ geometry->offsetTop() + pos.y,
+ CurrentTime);
+ if (buttonMask != oldButtonMask) {
+ for (int i = 0; i < maxButtons; i++) {
+ if ((buttonMask ^ oldButtonMask) & (1<<i)) {
+ if (buttonMask & (1<<i)) {
+ XTestFakeButtonEvent(dpy, i+1, True, CurrentTime);
+ } else {
+ XTestFakeButtonEvent(dpy, i+1, False, CurrentTime);
+ }
+ }
+ }
+ }
+ oldButtonMask = buttonMask;
+#endif
+}
+
+#ifdef HAVE_XTEST
+KeyCode XDesktop::XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
+ XkbDescPtr xkb;
+ XkbStateRec state;
+ unsigned keycode;
+
+ xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+ if (!xkb)
+ return 0;
+
+ XkbGetState(dpy, XkbUseCoreKbd, &state);
+
+ for (keycode = xkb->min_key_code;
+ keycode <= xkb->max_key_code;
+ keycode++) {
+ KeySym cursym;
+ unsigned int mods, out_mods;
+ // XkbStateFieldFromRec() doesn't work properly because
+ // state.lookup_mods isn't properly updated, so we do this manually
+ mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
+ XkbTranslateKeyCode(xkb, keycode, mods, &out_mods, &cursym);
+ if (cursym == keysym)
+ break;
+ }
+
+ if (keycode > xkb->max_key_code)
+ keycode = 0;
+
+ XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
+
+ return keycode;
+}
+#endif
+
+void XDesktop::keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
+#ifdef HAVE_XTEST
+ int keycode = 0;
+
+ if (!haveXtest)
+ return;
+
+ // Use scan code if provided and mapping exists
+ if (codeMap && rawKeyboard && xtcode < codeMapLen)
+ keycode = codeMap[xtcode];
+
+ if (!keycode) {
+ if (pressedKeys.find(keysym) != pressedKeys.end())
+ keycode = pressedKeys[keysym];
+ else {
+ // XKeysymToKeycode() doesn't respect state, so we have to use
+ // something slightly more complex
+ keycode = XkbKeysymToKeycode(dpy, keysym);
+ }
+ }
+
+ if (!keycode)
+ return;
+
+ if (down)
+ pressedKeys[keysym] = keycode;
+ else
+ pressedKeys.erase(keysym);
+
+ XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
+#endif
+}
+
+void XDesktop::clientCutText(const char* str, int len) {
+}
+
+
+bool XDesktop::handleGlobalEvent(XEvent* ev) {
+ if (ev->type == xkbEventBase + XkbEventCode) {
+ XkbEvent *kb = (XkbEvent *)ev;
+
+ if (kb->any.xkb_type != XkbIndicatorStateNotify)
+ return false;
+
+ vlog.debug("Got indicator update, mask is now 0x%x", kb->indicators.state);
+
+ ledState = 0;
+ for (int i = 0; i < XDESKTOP_N_LEDS; i++) {
+ if (kb->indicators.state & ledMasks[i])
+ ledState |= 1u << i;
+ }
+
+ if (running)
+ server->setLEDState(ledState);
+
+ return true;
+#ifdef HAVE_XDAMAGE
+ } else if (ev->type == xdamageEventBase) {
+ XDamageNotifyEvent* dev;
+ Rect rect;
+
+ if (!running)
+ return true;
+
+ dev = (XDamageNotifyEvent*)ev;
+ rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
+ server->add_changed(rect);
+
+ return true;
+#endif
+#ifdef HAVE_XFIXES
+ } else if (ev->type == xfixesEventBase + XFixesCursorNotify) {
+ XFixesCursorNotifyEvent* cev;
+
+ if (!running)
+ return true;
+
+ cev = (XFixesCursorNotifyEvent*)ev;
+
+ if (cev->subtype != XFixesDisplayCursorNotify)
+ return false;
+
+ return setCursor();
+#endif
+ }
+
+ return false;
+}
+
+bool XDesktop::setCursor()
+{
+ XFixesCursorImage *cim;
+
+ cim = XFixesGetCursorImage(dpy);
+ if (cim == NULL)
+ return false;
+
+ // Copied from XserverDesktop::setCursor() in
+ // unix/xserver/hw/vnc/XserverDesktop.cc and adapted to
+ // handle long -> U32 conversion for 64-bit Xlib
+ rdr::U8* cursorData;
+ rdr::U8 *out;
+ const unsigned long *pixels;
+
+ cursorData = new rdr::U8[cim->width * cim->height * 4];
+
+ // Un-premultiply alpha
+ pixels = cim->pixels;
+ out = cursorData;
+ for (int y = 0; y < cim->height; y++) {
+ for (int x = 0; x < cim->width; x++) {
+ rdr::U8 alpha;
+ rdr::U32 pixel = *pixels++;
+ rdr::U8 *in = (rdr::U8 *) &pixel;
+
+ alpha = in[3];
+ if (alpha == 0)
+ alpha = 1; // Avoid division by zero
+
+ *out++ = (unsigned)*in++ * 255/alpha;
+ *out++ = (unsigned)*in++ * 255/alpha;
+ *out++ = (unsigned)*in++ * 255/alpha;
+ *out++ = *in++;
+ }
+ }
+
+ try {
+ server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot),
+ cursorData);
+ } catch (rdr::Exception& e) {
+ vlog.error("XserverDesktop::setCursor: %s",e.str());
+ }
+
+ delete [] cursorData;
+ XFree(cim);
+ return true;
+}
diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h
new file mode 100644
index 0000000..c9106f8
--- /dev/null
+++ b/unix/x0vncserver/XDesktop.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright (C) 2004-2008 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright 2017 Peter Astrand <astrand@cendio.se> for Cendio AB
+ *
+ * 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 __XDESKTOP_H__
+#define __XDESKTOP_H__
+
+#include <rfb/VNCServerST.h>
+#include <tx/TXWindow.h>
+
+#include <X11/XKBlib.h>
+#ifdef HAVE_XDAMAGE
+#include <X11/extensions/Xdamage.h>
+#endif
+
+class Geometry;
+class XPixelBuffer;
+
+// number of XKb indicator leds to handle
+#define XDESKTOP_N_LEDS 3
+
+class XDesktop : public rfb::SDesktop, public TXGlobalEventHandler
+{
+public:
+ XDesktop(Display* dpy_, Geometry *geometry);
+ virtual ~XDesktop();
+ void poll();
+ // -=- SDesktop interface
+ virtual void start(rfb::VNCServer* vs);
+ virtual void stop();
+ bool isRunning();
+ virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
+ KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym);
+ virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down);
+ virtual void clientCutText(const char* str, int len);
+ // -=- TXGlobalEventHandler interface
+ virtual bool handleGlobalEvent(XEvent* ev);
+
+protected:
+ Display* dpy;
+ Geometry* geometry;
+ XPixelBuffer* pb;
+ rfb::VNCServerST* server;
+ int oldButtonMask;
+ bool haveXtest;
+ bool haveDamage;
+ int maxButtons;
+ std::map<KeySym, KeyCode> pressedKeys;
+ bool running;
+#ifdef HAVE_XDAMAGE
+ Damage damage;
+ int xdamageEventBase;
+#endif
+ int xkbEventBase;
+#ifdef HAVE_XFIXES
+ int xfixesEventBase;
+#endif
+ int ledMasks[XDESKTOP_N_LEDS];
+ unsigned ledState;
+ const unsigned short *codeMap;
+ unsigned codeMapLen;
+ bool setCursor();
+};
+
+#endif // __XDESKTOP_H__
diff --git a/unix/x0vncserver/XPixelBuffer.h b/unix/x0vncserver/XPixelBuffer.h
index da03161..18c85fe 100644
--- a/unix/x0vncserver/XPixelBuffer.h
+++ b/unix/x0vncserver/XPixelBuffer.h
@@ -28,23 +28,21 @@
#include <x0vncserver/Image.h>
#include <x0vncserver/PollingManager.h>
-using namespace rfb;
-
//
// XPixelBuffer is an Image-based implementation of FullFramePixelBuffer.
//
-class XPixelBuffer : public FullFramePixelBuffer
+class XPixelBuffer : public rfb::FullFramePixelBuffer
{
public:
- XPixelBuffer(Display *dpy, ImageFactory &factory, const Rect &rect);
+ XPixelBuffer(Display *dpy, ImageFactory &factory, const rfb::Rect &rect);
virtual ~XPixelBuffer();
// Provide access to the underlying Image object.
const Image *getImage() const { return m_image; }
// Detect changed pixels, notify the server.
- inline void poll(VNCServer *server) { m_poller->poll(server); }
+ inline void poll(rfb::VNCServer *server) { m_poller->poll(server); }
// Override PixelBuffer::grabRegion().
virtual void grabRegion(const rfb::Region& region);
@@ -59,7 +57,7 @@
// Copy pixels from the screen to the pixel buffer,
// for the specified rectangular area of the buffer.
- inline void grabRect(const Rect &r) {
+ inline void grabRect(const rfb::Rect &r) {
m_image->get(DefaultRootWindow(m_dpy),
m_offsetLeft + r.tl.x, m_offsetTop + r.tl.y,
r.width(), r.height(), r.tl.x, r.tl.y);
diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx
index 6fd6bc3..22525d5 100644
--- a/unix/x0vncserver/x0vncserver.cxx
+++ b/unix/x0vncserver/x0vncserver.cxx
@@ -31,7 +31,6 @@
#include <rfb/Configuration.h>
#include <rfb/Timer.h>
#include <network/TcpSocket.h>
-#include <tx/TXWindow.h>
#include <vncconfig/QueryConnectDialog.h>
@@ -39,46 +38,17 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
-#include <X11/XKBlib.h>
-#ifdef HAVE_XTEST
-#include <X11/extensions/XTest.h>
-#endif
-#ifdef HAVE_XDAMAGE
-#include <X11/extensions/Xdamage.h>
-#endif
-#ifdef HAVE_XFIXES
-#include <X11/extensions/Xfixes.h>
-#endif
+#include <x0vncserver/XDesktop.h>
#include <x0vncserver/Geometry.h>
#include <x0vncserver/Image.h>
-#include <x0vncserver/XPixelBuffer.h>
#include <x0vncserver/PollingScheduler.h>
-extern const unsigned short code_map_qnum_to_xorgevdev[];
-extern const unsigned int code_map_qnum_to_xorgevdev_len;
-
-extern const unsigned short code_map_qnum_to_xorgkbd[];
-extern const unsigned int code_map_qnum_to_xorgkbd_len;
-
-// XXX Lynx/OS 2.3: protos for select(), bzero()
-#ifdef Lynx
-#include <sys/proto.h>
-#endif
-
extern char buildtime[];
using namespace rfb;
using namespace network;
-// number of XKb indicator leds to handle
-static const int N_LEDS = 3;
-
-// order is important as it must match RFB extension
-static const char * ledNames[N_LEDS] = {
- "Scroll Lock", "Num Lock", "Caps Lock"
-};
-
static LogWriter vlog("Main");
IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling "
@@ -87,8 +57,6 @@
IntParameter maxProcessorUsage("MaxProcessorUsage", "Maximum percentage of "
"CPU time to be consumed", 35);
BoolParameter useShm("UseSHM", "Use MIT-SHM extension if available", true);
-BoolParameter useOverlay("OverlayMode", "Use overlay mode under "
- "IRIX or Solaris", true);
StringParameter displayname("display", "The X display", "");
IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",5900);
IntParameter queryConnectTimeout("QueryConnectTimeout",
@@ -157,399 +125,6 @@
};
-class XDesktop : public SDesktop, public TXGlobalEventHandler
-{
-public:
- XDesktop(Display* dpy_, Geometry *geometry_)
- : dpy(dpy_), geometry(geometry_), pb(0), server(0),
- oldButtonMask(0), haveXtest(false), haveDamage(false),
- maxButtons(0), running(false), ledMasks(), ledState(0),
- codeMap(0), codeMapLen(0)
- {
- int major, minor;
-
- int xkbOpcode, xkbErrorBase;
-
- major = XkbMajorVersion;
- minor = XkbMinorVersion;
- if (!XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase,
- &xkbErrorBase, &major, &minor)) {
- vlog.error("XKEYBOARD extension not present");
- throw Exception();
- }
-
- XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask,
- XkbIndicatorStateNotifyMask);
-
- // figure out bit masks for the indicators we are interested in
- for (int i = 0; i < N_LEDS; i++) {
- Atom a;
- int shift;
- Bool on;
-
- a = XInternAtom(dpy, ledNames[i], True);
- if (!a || !XkbGetNamedIndicator(dpy, a, &shift, &on, NULL, NULL))
- continue;
-
- ledMasks[i] = 1u << shift;
- vlog.debug("Mask for '%s' is 0x%x", ledNames[i], ledMasks[i]);
- if (on)
- ledState |= 1u << i;
- }
-
- // X11 unfortunately uses keyboard driver specific keycodes and provides no
- // direct way to query this, so guess based on the keyboard mapping
- XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
- if (desc && desc->names) {
- char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
-
- if (keycodes) {
- if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
- codeMap = code_map_qnum_to_xorgevdev;
- codeMapLen = code_map_qnum_to_xorgevdev_len;
- vlog.info("Using evdev codemap\n");
- } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
- codeMap = code_map_qnum_to_xorgkbd;
- codeMapLen = code_map_qnum_to_xorgkbd_len;
- vlog.info("Using xorgkbd codemap\n");
- } else {
- vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
- }
- XFree(keycodes);
- } else {
- vlog.debug("Unable to get keycode map\n");
- }
-
- XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
- }
-
-#ifdef HAVE_XTEST
- int xtestEventBase;
- int xtestErrorBase;
-
- if (XTestQueryExtension(dpy, &xtestEventBase,
- &xtestErrorBase, &major, &minor)) {
- XTestGrabControl(dpy, True);
- vlog.info("XTest extension present - version %d.%d",major,minor);
- haveXtest = true;
- } else {
-#endif
- vlog.info("XTest extension not present");
- vlog.info("Unable to inject events or display while server is grabbed");
-#ifdef HAVE_XTEST
- }
-#endif
-
-#ifdef HAVE_XDAMAGE
- int xdamageErrorBase;
-
- if (XDamageQueryExtension(dpy, &xdamageEventBase, &xdamageErrorBase)) {
- haveDamage = true;
- } else {
-#endif
- vlog.info("DAMAGE extension not present");
- vlog.info("Will have to poll screen for changes");
-#ifdef HAVE_XDAMAGE
- }
-#endif
-
-#ifdef HAVE_XFIXES
- int xfixesErrorBase;
-
- if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
- XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
- XFixesDisplayCursorNotifyMask);
- } else {
-#endif
- vlog.info("XFIXES extension not present");
- vlog.info("Will not be able to display cursors");
-#ifdef HAVE_XFIXES
- }
-#endif
-
- TXWindow::setGlobalEventHandler(this);
- }
- virtual ~XDesktop() {
- stop();
- }
-
- inline void poll() {
- if (pb and not haveDamage)
- pb->poll(server);
- if (running) {
- Window root, child;
- int x, y, wx, wy;
- unsigned int mask;
- XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
- &x, &y, &wx, &wy, &mask);
- server->setCursorPos(rfb::Point(x, y));
- }
- }
-
- // -=- SDesktop interface
-
- virtual void start(VNCServer* vs) {
-
- // Determine actual number of buttons of the X pointer device.
- unsigned char btnMap[8];
- int numButtons = XGetPointerMapping(dpy, btnMap, 8);
- maxButtons = (numButtons > 8) ? 8 : numButtons;
- vlog.info("Enabling %d button%s of X pointer device",
- maxButtons, (maxButtons != 1) ? "s" : "");
-
- // Create an ImageFactory instance for producing Image objects.
- ImageFactory factory((bool)useShm, (bool)useOverlay);
-
- // Create pixel buffer and provide it to the server object.
- pb = new XPixelBuffer(dpy, factory, geometry->getRect());
- vlog.info("Allocated %s", pb->getImage()->classDesc());
-
- server = (VNCServerST *)vs;
- server->setPixelBuffer(pb);
-
-#ifdef HAVE_XDAMAGE
- if (haveDamage) {
- damage = XDamageCreate(dpy, DefaultRootWindow(dpy),
- XDamageReportRawRectangles);
- }
-#endif
-
- server->setLEDState(ledState);
-
- running = true;
- }
-
- virtual void stop() {
- running = false;
-
-#ifdef HAVE_XDAMAGE
- if (haveDamage)
- XDamageDestroy(dpy, damage);
-#endif
-
- delete pb;
- pb = 0;
- }
-
- inline bool isRunning() {
- return running;
- }
-
- virtual void pointerEvent(const Point& pos, int buttonMask) {
-#ifdef HAVE_XTEST
- if (!haveXtest) return;
- XTestFakeMotionEvent(dpy, DefaultScreen(dpy),
- geometry->offsetLeft() + pos.x,
- geometry->offsetTop() + pos.y,
- CurrentTime);
- if (buttonMask != oldButtonMask) {
- for (int i = 0; i < maxButtons; i++) {
- if ((buttonMask ^ oldButtonMask) & (1<<i)) {
- if (buttonMask & (1<<i)) {
- XTestFakeButtonEvent(dpy, i+1, True, CurrentTime);
- } else {
- XTestFakeButtonEvent(dpy, i+1, False, CurrentTime);
- }
- }
- }
- }
- oldButtonMask = buttonMask;
-#endif
- }
-
-#ifdef HAVE_XTEST
- KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
- XkbDescPtr xkb;
- XkbStateRec state;
- unsigned keycode;
-
- xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
- if (!xkb)
- return 0;
-
- XkbGetState(dpy, XkbUseCoreKbd, &state);
-
- for (keycode = xkb->min_key_code;
- keycode <= xkb->max_key_code;
- keycode++) {
- KeySym cursym;
- unsigned int mods, out_mods;
- // XkbStateFieldFromRec() doesn't work properly because
- // state.lookup_mods isn't properly updated, so we do this manually
- mods = XkbBuildCoreState(XkbStateMods(&state), state.group);
- XkbTranslateKeyCode(xkb, keycode, mods, &out_mods, &cursym);
- if (cursym == keysym)
- break;
- }
-
- if (keycode > xkb->max_key_code)
- keycode = 0;
-
- XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
-
- return keycode;
- }
-#endif
-
- virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
-#ifdef HAVE_XTEST
- int keycode = 0;
-
- if (!haveXtest)
- return;
-
- // Use scan code if provided and mapping exists
- if (codeMap && rawKeyboard && xtcode < codeMapLen)
- keycode = codeMap[xtcode];
-
- if (!keycode) {
- if (pressedKeys.find(keysym) != pressedKeys.end())
- keycode = pressedKeys[keysym];
- else {
- // XKeysymToKeycode() doesn't respect state, so we have to use
- // something slightly more complex
- keycode = XkbKeysymToKeycode(dpy, keysym);
- }
- }
-
- if (!keycode)
- return;
-
- if (down)
- pressedKeys[keysym] = keycode;
- else
- pressedKeys.erase(keysym);
-
- XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
-#endif
- }
-
- virtual void clientCutText(const char* str, int len) {
- }
-
- // -=- TXGlobalEventHandler interface
-
- virtual bool handleGlobalEvent(XEvent* ev) {
- if (ev->type == xkbEventBase + XkbEventCode) {
- XkbEvent *kb = (XkbEvent *)ev;
-
- if (kb->any.xkb_type != XkbIndicatorStateNotify)
- return false;
-
- vlog.debug("Got indicator update, mask is now 0x%x", kb->indicators.state);
-
- ledState = 0;
- for (int i = 0; i < N_LEDS; i++) {
- if (kb->indicators.state & ledMasks[i])
- ledState |= 1u << i;
- }
-
- if (running)
- server->setLEDState(ledState);
-
- return true;
-#ifdef HAVE_XDAMAGE
- } else if (ev->type == xdamageEventBase) {
- XDamageNotifyEvent* dev;
- Rect rect;
-
- if (!running)
- return true;
-
- dev = (XDamageNotifyEvent*)ev;
- rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
- server->add_changed(rect);
-
- return true;
-#endif
-#ifdef HAVE_XFIXES
- } else if (ev->type == xfixesEventBase + XFixesCursorNotify) {
- XFixesCursorNotifyEvent* cev;
- XFixesCursorImage *cim;
-
- if (!running)
- return true;
-
- cev = (XFixesCursorNotifyEvent*)ev;
-
- if (cev->subtype != XFixesDisplayCursorNotify)
- return false;
-
- cim = XFixesGetCursorImage(dpy);
- if (cim == NULL)
- return false;
-
- // Copied from XserverDesktop::setCursor() in
- // unix/xserver/hw/vnc/XserverDesktop.cc and adapted to
- // handle long -> U32 conversion for 64-bit Xlib
- rdr::U8* cursorData;
- rdr::U8 *out;
- const unsigned long *pixels;
-
- cursorData = new rdr::U8[cim->width * cim->height * 4];
-
- // Un-premultiply alpha
- pixels = cim->pixels;
- out = cursorData;
- for (int y = 0; y < cim->height; y++) {
- for (int x = 0; x < cim->width; x++) {
- rdr::U8 alpha;
- rdr::U32 pixel = *pixels++;
- rdr::U8 *in = (rdr::U8 *) &pixel;
-
- alpha = in[3];
- if (alpha == 0)
- alpha = 1; // Avoid division by zero
-
- *out++ = (unsigned)*in++ * 255/alpha;
- *out++ = (unsigned)*in++ * 255/alpha;
- *out++ = (unsigned)*in++ * 255/alpha;
- *out++ = *in++;
- }
- }
-
- try {
- server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot),
- cursorData);
- } catch (rdr::Exception& e) {
- vlog.error("XserverDesktop::setCursor: %s",e.str());
- }
-
- delete [] cursorData;
- XFree(cim);
- return true;
-#endif
- }
-
- return false;
- }
-
-protected:
- Display* dpy;
- Geometry* geometry;
- XPixelBuffer* pb;
- VNCServerST* server;
- int oldButtonMask;
- bool haveXtest;
- bool haveDamage;
- int maxButtons;
- std::map<KeySym, KeyCode> pressedKeys;
- bool running;
-#ifdef HAVE_XDAMAGE
- Damage damage;
- int xdamageEventBase;
-#endif
- int xkbEventBase;
-#ifdef HAVE_XFIXES
- int xfixesEventBase;
-#endif
- int ledMasks[N_LEDS];
- unsigned ledState;
- const unsigned short *codeMap;
- unsigned codeMapLen;
-};
-
-
class FileTcpFilter : public TcpFilter
{
@@ -683,6 +258,9 @@
Configuration::enableServerParams();
+ // Disable configuration parameters which we do not support
+ Configuration::removeParam("AcceptSetDesktopSize");
+
for (int i = 1; i < argc; i++) {
if (Configuration::setParam(argv[i]))
continue;
diff --git a/unix/x0vncserver/x0vncserver.man b/unix/x0vncserver/x0vncserver.man
index 804a70f..4f47e59 100644
--- a/unix/x0vncserver/x0vncserver.man
+++ b/unix/x0vncserver/x0vncserver.man
@@ -227,13 +227,6 @@
the screen. Default is on.
.
.TP
-.B OverlayMode
-Use overlay mode in IRIX or Solaris (does not have effect in other systems).
-This enables system-specific access to complete full-color version of the
-screen (the default X visual often provides 256 colors). Also, in overlay
-mode, \fBx0vncserver\fP can show correct mouse cursor. Default is on.
-.
-.TP
.B ZlibLevel
Zlib compression level for ZRLE encoding (it does not affect Tight encoding).
Acceptable values are between 0 and 9. Default is to use the standard
diff --git a/win/winvnc/winvnc.cxx b/win/winvnc/winvnc.cxx
index aa41bcb..5623421 100644
--- a/win/winvnc/winvnc.cxx
+++ b/win/winvnc/winvnc.cxx
@@ -78,7 +78,7 @@
printf("\nLog destinations:\n");
Logger::listLoggers();
printf("\nAvailable configuration parameters:\n");
- Configuration::listParams(ConfServer);
+ Configuration::listParams(79, 14);
}
static void MsgBoxOrLog(const char* msg, bool isError=false) {