From 76b48676844bc7aa0511b8371ef6347b2e8ad545 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Tue, 25 Apr 2017 15:27:17 +0200 Subject: nxcompshad: Switch to autoreconf. --- Makefile | 2 +- debian/copyright | 50 +- debian/libxcompshad-dev.install | 1 + debian/rules | 2 +- nx-X11/lib/X11/Imakefile | 2 +- nx-X11/programs/Xserver/Imakefile | 12 +- nxcompshad/.gitignore | 23 +- nxcompshad/Core.cpp | 622 --------- nxcompshad/Core.h | 212 --- nxcompshad/Input.cpp | 175 --- nxcompshad/Input.h | 99 -- nxcompshad/Logger.cpp | 124 -- nxcompshad/Logger.h | 167 --- nxcompshad/Makefile.am | 21 + nxcompshad/Makefile.in | 251 ---- nxcompshad/Manager.cpp | 260 ---- nxcompshad/Manager.h | 123 -- nxcompshad/Misc.h | 50 - nxcompshad/Poller.h | 39 - nxcompshad/Regions.h | 43 - nxcompshad/Shadow.cpp | 478 ------- nxcompshad/Shadow.h | 109 -- nxcompshad/Updater.cpp | 391 ------ nxcompshad/Updater.h | 103 -- nxcompshad/Win.cpp | 1145 ---------------- nxcompshad/Win.h | 232 ---- nxcompshad/X11.cpp | 1594 ---------------------- nxcompshad/X11.h | 139 -- nxcompshad/X11/include/XTest_nxcompshad.h | 71 - nxcompshad/X11/include/Xdamage_nxcompshad.h | 92 -- nxcompshad/X11/include/Xrandr_nxcompshad.h | 80 -- nxcompshad/configure.ac | 53 + nxcompshad/configure.in | 307 ----- nxcompshad/include/Shadow.h | 109 ++ nxcompshad/install-sh | 238 ---- nxcompshad/m4/nx-macros.m4 | 1 + nxcompshad/nxcompshad.pc.in | 2 +- nxcompshad/src/Core.cpp | 626 +++++++++ nxcompshad/src/Core.h | 212 +++ nxcompshad/src/Input.cpp | 179 +++ nxcompshad/src/Input.h | 99 ++ nxcompshad/src/Logger.cpp | 128 ++ nxcompshad/src/Logger.h | 167 +++ nxcompshad/src/Makefile.am | 45 + nxcompshad/src/Manager.cpp | 264 ++++ nxcompshad/src/Manager.h | 123 ++ nxcompshad/src/Misc.h | 50 + nxcompshad/src/Poller.h | 39 + nxcompshad/src/Regions.h | 43 + nxcompshad/src/Shadow.cpp | 482 +++++++ nxcompshad/src/Updater.cpp | 395 ++++++ nxcompshad/src/Updater.h | 103 ++ nxcompshad/src/Win.cpp | 1149 ++++++++++++++++ nxcompshad/src/Win.h | 232 ++++ nxcompshad/src/X11.cpp | 1598 +++++++++++++++++++++++ nxcompshad/src/X11.h | 139 ++ nxcompshad/src/X11/include/XTest_nxcompshad.h | 71 + nxcompshad/src/X11/include/Xdamage_nxcompshad.h | 92 ++ nxcompshad/src/X11/include/Xrandr_nxcompshad.h | 80 ++ 59 files changed, 6558 insertions(+), 7180 deletions(-) delete mode 100644 nxcompshad/Core.cpp delete mode 100644 nxcompshad/Core.h delete mode 100644 nxcompshad/Input.cpp delete mode 100644 nxcompshad/Input.h delete mode 100644 nxcompshad/Logger.cpp delete mode 100644 nxcompshad/Logger.h create mode 100644 nxcompshad/Makefile.am delete mode 100644 nxcompshad/Makefile.in delete mode 100644 nxcompshad/Manager.cpp delete mode 100644 nxcompshad/Manager.h delete mode 100644 nxcompshad/Misc.h delete mode 100644 nxcompshad/Poller.h delete mode 100644 nxcompshad/Regions.h delete mode 100644 nxcompshad/Shadow.cpp delete mode 100644 nxcompshad/Shadow.h delete mode 100644 nxcompshad/Updater.cpp delete mode 100644 nxcompshad/Updater.h delete mode 100644 nxcompshad/Win.cpp delete mode 100644 nxcompshad/Win.h delete mode 100644 nxcompshad/X11.cpp delete mode 100644 nxcompshad/X11.h delete mode 100644 nxcompshad/X11/include/XTest_nxcompshad.h delete mode 100644 nxcompshad/X11/include/Xdamage_nxcompshad.h delete mode 100644 nxcompshad/X11/include/Xrandr_nxcompshad.h create mode 100644 nxcompshad/configure.ac delete mode 100644 nxcompshad/configure.in create mode 100644 nxcompshad/include/Shadow.h delete mode 100755 nxcompshad/install-sh create mode 120000 nxcompshad/m4/nx-macros.m4 create mode 100644 nxcompshad/src/Core.cpp create mode 100644 nxcompshad/src/Core.h create mode 100644 nxcompshad/src/Input.cpp create mode 100644 nxcompshad/src/Input.h create mode 100644 nxcompshad/src/Logger.cpp create mode 100644 nxcompshad/src/Logger.h create mode 100644 nxcompshad/src/Makefile.am create mode 100644 nxcompshad/src/Manager.cpp create mode 100644 nxcompshad/src/Manager.h create mode 100644 nxcompshad/src/Misc.h create mode 100644 nxcompshad/src/Poller.h create mode 100644 nxcompshad/src/Regions.h create mode 100644 nxcompshad/src/Shadow.cpp create mode 100644 nxcompshad/src/Updater.cpp create mode 100644 nxcompshad/src/Updater.h create mode 100644 nxcompshad/src/Win.cpp create mode 100644 nxcompshad/src/Win.h create mode 100644 nxcompshad/src/X11.cpp create mode 100644 nxcompshad/src/X11.h create mode 100644 nxcompshad/src/X11/include/XTest_nxcompshad.h create mode 100644 nxcompshad/src/X11/include/Xdamage_nxcompshad.h create mode 100644 nxcompshad/src/X11/include/Xrandr_nxcompshad.h diff --git a/Makefile b/Makefile index 6fb11333c..d38015a00 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ build-full: # nxcomp{ext,shad}. cd nx-X11/lib && make - cd nxcompshad && autoconf && (${CONFIGURE}) && ${MAKE} + cd nxcompshad && autoreconf -vfsi && (${CONFIGURE}) && ${MAKE} ./mesa-quilt push -a diff --git a/debian/copyright b/debian/copyright index b08ec0335..d9ef896b0 100644 --- a/debian/copyright +++ b/debian/copyright @@ -80,25 +80,25 @@ Files: nx-X11/extras/Mesa/src/mesa/main/WSDrawBuffer.h nx-X11/programs/Xserver/hw/nxagent/compext/Rle.h nx-X11/programs/Xserver/hw/nxagent/compext/Z.c nx-X11/programs/Xserver/hw/nxagent/compext/Z.h - nxcompshad/Core.cpp - nxcompshad/Core.h - nxcompshad/Input.cpp - nxcompshad/Input.h - nxcompshad/Logger.cpp - nxcompshad/Logger.h - nxcompshad/Manager.cpp - nxcompshad/Manager.h - nxcompshad/Misc.h - nxcompshad/Poller.h - nxcompshad/Regions.h - nxcompshad/Shadow.cpp - nxcompshad/Shadow.h - nxcompshad/Updater.cpp - nxcompshad/Updater.h - nxcompshad/Win.cpp - nxcompshad/Win.h - nxcompshad/X11.cpp - nxcompshad/X11.h + nxcompshad/include/Shadow.h + nxcompshad/src/Core.cpp + nxcompshad/src/Core.h + nxcompshad/src/Input.cpp + nxcompshad/src/Input.h + nxcompshad/src/Logger.cpp + nxcompshad/src/Logger.h + nxcompshad/src/Manager.cpp + nxcompshad/src/Manager.h + nxcompshad/src/Misc.h + nxcompshad/src/Poller.h + nxcompshad/src/Regions.h + nxcompshad/src/Shadow.cpp + nxcompshad/src/Updater.cpp + nxcompshad/src/Updater.h + nxcompshad/src/Win.cpp + nxcompshad/src/Win.h + nxcompshad/src/X11.cpp + nxcompshad/src/X11.h Copyright: 2001, 2011, NoMachine (http://www.nomachine.com) 2008-2014, Oleksandr Shneyder 2011-2016, Mike Gabriel */ @@ -1001,7 +1001,7 @@ Files: nx-X11/include/XWDFile.h nx-X11/programs/Xserver/record/record.c nx-X11/programs/Xserver/record/set.c nx-X11/programs/Xserver/record/set.h - nxcompshad/X11/include/XTest_nxcompshad.h + nxcompshad/src/X11/include/XTest_nxcompshad.h Copyright: 1985, 1987, 1990, 1998, The Open Group 1985, 1987, 1994, 1998, The Open Group 1985, 1987, 1998, The Open Group @@ -1452,7 +1452,7 @@ Files: nx-X11/include/extensions/composite.h nx-X11/programs/Xserver/xfixes/xfixes.h nx-X11/programs/Xserver/xfixes/xfixesint.h nx-X11/programs/Xserver/Xext/shmint.h - nxcompshad/X11/include/Xdamage_nxcompshad.h + nxcompshad/src/X11/include/Xdamage_nxcompshad.h Copyright: 1998, Keith Packard 1999, Keith Packard 2002, Keith Packard @@ -2310,7 +2310,7 @@ Copyright: 2000, Compaq Computer Corporation License: MIT~X11 Files: nx-X11/programs/Xserver/hw/nxagent/X11/include/Xrandr_nxagent.h - nxcompshad/X11/include/Xrandr_nxcompshad.h + nxcompshad/src/X11/include/Xrandr_nxcompshad.h Copyright: 2000, Compaq Computer Corporation, Inc 2002, Hewlett-Packard Company, Inc 2006, Intel Corporation @@ -2908,10 +2908,11 @@ Files: ChangeLog nxcomp/VERSION nxcomp/configure.in nxcomp/nxcomp.pc.in - nxcompshad/Makefile.in + nxcompshad/Makefile.am nxcompshad/VERSION - nxcompshad/configure.in + nxcompshad/configure.ac nxcompshad/nxcompshad.pc.in + nxcompshad/src/Makefile.am nxproxy/VERSION nxproxy/man/nxproxy.1 nxproxy/Makefile.am @@ -2951,7 +2952,6 @@ Copyright: *No copyright* License: public-domain Files: nxcomp/install-sh - nxcompshad/install-sh Copyright: 1994, X Consortium License: Expat~NoAdvert Comment: diff --git a/debian/libxcompshad-dev.install b/debian/libxcompshad-dev.install index 2010f5950..68318ee03 100644 --- a/debian/libxcompshad-dev.install +++ b/debian/libxcompshad-dev.install @@ -1,3 +1,4 @@ usr/lib/*/libXcompshad.so +usr/lib/*/libXcompshad.a usr/include/*/nx/Shadow.h usr/lib/*/pkgconfig/nxcompshad.pc diff --git a/debian/rules b/debian/rules index adfc34e5e..b59ba83a5 100755 --- a/debian/rules +++ b/debian/rules @@ -25,7 +25,7 @@ override_dh_install: # remove static libs rm debian/tmp/usr/lib/$(DEB_BUILD_MULTIARCH)/libXcomp.a - rm debian/tmp/usr/lib/$(DEB_BUILD_MULTIARCH)/libXcompshad.a + rm debian/tmp/usr/lib/$(DEB_BUILD_MULTIARCH)/libXcompshad.la # remove extras, GL, and other unneeded headers rm -R debian/tmp/usr/include/$(DEB_BUILD_MULTIARCH)/GL/ diff --git a/nx-X11/lib/X11/Imakefile b/nx-X11/lib/X11/Imakefile index 055cbec33..5b289fae8 100644 --- a/nx-X11/lib/X11/Imakefile +++ b/nx-X11/lib/X11/Imakefile @@ -87,7 +87,7 @@ NX_XCOMPLIBTARGET = $(NX_XCOMPLIBDIR)/$(NX_XCOMPLIBNAME) NX_REQUIREDLIBS = -L$(NX_XCOMPLIBDIR) -l$(NX_XCOMPLIBLINK) NX_XCOMPCONFIGTARGET = $(NX_XCOMPLIBDIR)/config.status -NX_XCOMPEXTLIBDIR = $(XTOP)/../nxcompext +NX_XCOMPEXTLIBDIR = $(XTOP)/../nxcompext/src/.libs NX_XCOMPEXTLIBTARGET = $(NX_XCOMPEXTLIBDIR)/$(NX_XCOMPEXTLIBNAME) NX_XCOMPEXTCONFIGTARGET = $(NX_XCOMPEXTLIBDIR)/config.status diff --git a/nx-X11/programs/Xserver/Imakefile b/nx-X11/programs/Xserver/Imakefile index c5bbbeb75..ed49313ee 100644 --- a/nx-X11/programs/Xserver/Imakefile +++ b/nx-X11/programs/Xserver/Imakefile @@ -221,8 +221,8 @@ NX_XCOMP_HEADERS = \ ../../../nxcomp/NXvars.h \ $(NULL) -NX_XCOMPSHAD_HEADERS = \ - ../../../nxcompshad/Shadow.h \ +NX_XCOMPSHAD_HEADERS = \ + ../../../nxcompshad/include/Shadow.h \ $(NULL) NX_HEADERS = \ @@ -316,7 +316,7 @@ $(NXAGENTOBJS) $(NXAGENTLIBS) $(NXAGENTSYSLIBS):: $(NXAGENTDIRS) #if defined(SunArchitecture) NXAGENTNXLIBS = -L/usr/sfw/lib \ -L../../../nxcomp \ - -L../../../nxcompshad \ + -L../../../nxcompshad/src/.libs \ -lrt \ -lXcomp \ -lXcompshad \ @@ -331,7 +331,7 @@ NXAGENTNXLIBS = -L/usr/sfw/lib \ $(NULL) #elif defined(cygwinArchitecture) NXAGENTNXLIBS = -L../../../nxcomp \ - -L../../../nxcompshad \ + -L../../../nxcompshad/src/.libs \ -lXcomp \ -lXcompshad \ -lXrender \ @@ -345,7 +345,7 @@ NXAGENTNXLIBS = -L../../../nxcomp \ #elif defined(OpenBSDArchitecture) NXAGENTNXLIBS = -L../../../nxcomp \ -L../../../nx-X11/exports/lib \ - -L../../../nxcompshad \ + -L../../../nxcompshad/src/.libs \ -lkvm \ -lXcomp \ -lXcompshad \ @@ -360,7 +360,7 @@ NXAGENTNXLIBS = -L../../../nxcomp \ $(NULL) #else NXAGENTNXLIBS = -L../../../nxcomp \ - -L../../../nxcompshad \ + -L../../../nxcompshad/src/.libs \ -lXcomp \ -lXcompshad \ -lXrender \ diff --git a/nxcompshad/.gitignore b/nxcompshad/.gitignore index f083c6b27..1eefcb7bf 100644 --- a/nxcompshad/.gitignore +++ b/nxcompshad/.gitignore @@ -1,2 +1,23 @@ -nxcompshad.pc Makefile +Makefile.in +aclocal.m4 +build-aux/compile +build-aux/config.guess +build-aux/config.sub +build-aux/depcomp +build-aux/install-sh +build-aux/ltmain.sh +build-aux/missing +config.h +config.h.in +libtool +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +nxcompshad.pc +src/.deps/ +src/Makefile +src/Makefile.in +stamp-h1 diff --git a/nxcompshad/Core.cpp b/nxcompshad/Core.cpp deleted file mode 100644 index 1682d343f..000000000 --- a/nxcompshad/Core.cpp +++ /dev/null @@ -1,622 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include "Core.h" -#include "Logger.h" - -const int CorePoller::maxSliceHeight_ = 20; -const int CorePoller::minSliceHeight_ = 3; - -const char CorePoller::interlace_[] = -{ - 0, 16, - 8, 24, - 4, 20, 12, 28, - 2, 18, 10, 26, 6, 22, 14, 30, - 1, 17, - 9, 25, - 5, 21, 13, 29, - 3, 19, 11, 27, 7, 23, 15, 31 -}; - -CorePoller::CorePoller(Input *input, Display *display) : input_(input) -{ - logTrace("CorePoller::CorePoller"); - - buffer_ = NULL; - lastUpdatedRegion_ = NULL; - lineStatus_ = NULL; - linePriority_ = NULL; - lefts_ = NULL; - rights_ = NULL; -} - -CorePoller::~CorePoller() -{ - logTrace("CorePoller::~CorePoller"); - - if (buffer_ != NULL) - { - delete [] buffer_; - - buffer_ = NULL; - } - - if (lastUpdatedRegion_ != NULL) - { - XDestroyRegion(lastUpdatedRegion_); - - lastUpdatedRegion_ = NULL; - } - - if (lineStatus_ != NULL) - { - delete [] lineStatus_; - - lineStatus_ = NULL; - } - - if (linePriority_ != NULL) - { - delete [] linePriority_; - - linePriority_ = NULL; - } - - if (lefts_ != NULL) - { - delete [] lefts_; - - lefts_ = NULL; - } - - if (rights_ != NULL) - { - delete [] rights_; - - rights_ = NULL; - } -} - -int CorePoller::init() -{ - logTrace("CorePoller::init"); - - createFrameBuffer(); - - if (buffer_ == NULL) - { - logError("CorePoller::init", ESET(ENOMEM)); - - return -1; - } - - logTest("CorePoller::init", "Allocated frame buffer at [%p] for [%d] bytes.", - buffer_, bpl_ * height_); - - if (lastUpdatedRegion_ != NULL) - { - XDestroyRegion(lastUpdatedRegion_); - - lastUpdatedRegion_ = NULL; - } - - lastUpdatedRegion_ = XCreateRegion(); - - if (lineStatus_ != NULL) - { - delete[] lineStatus_; - } - - lineStatus_ = new LineStatus[height_ + 1]; - - if (lineStatus_ == NULL) - { - logError("CorePoller::init", ESET(ENOMEM)); - - return -1; - } - - // - // We need this boundary element to - // speed up the algo. - // - - if (linePriority_ != NULL) - { - delete[] linePriority_; - } - - linePriority_ = new int [height_ + 1]; - - if (linePriority_ == NULL) - { - logError("CorePoller::init", ESET(ENOMEM)); - - return -1; - } - - for (unsigned int i = 0; i < height_; i++) - { - linePriority_[i] = HIGHEST_PRIORITY; - } - - if (lefts_ != NULL) - { - delete[] lefts_; - } - - lefts_ = new int [height_]; - - if (rights_ != NULL) - { - delete[] rights_; - } - - rights_ = new int [height_]; - - for (unsigned int i = 0; i < height_; i++) - { - rights_[i] = lefts_[i] = 0; - } - - return 1; -} - -int CorePoller::isChanged(int (*checkIfInputCallback)(void *), void *arg, int *suspended) -{ - logTrace("CorePoller::isChanged"); - -#if defined(__CYGWIN32__) || defined(WIN32) - - checkDesktop(); - -#endif - -#if !defined(__CYGWIN32__) && !defined(WIN32) - - if (mirror_ == 1) - { - int result = mirrorChanges_; - - mirrorChanges_ = 0; - - return result; - } - -#endif - - logDebug("CorePoller:isChanged", "Going to use default polling algorithm.\n"); - - // - // In order to allow this function to - // be suspended and resumed later, we - // need to save these two status vars. - // - - static int idxIlace = 0; - static int curLine = 0; - - - const long timeout = 50; - long oldTime; - long newTime; - struct timeval ts; - - gettimeofday(&ts, NULL); - - oldTime = ts.tv_sec * 1000 + ts.tv_usec / 1000; - - if (curLine == 0) // && idxIlace == 0 ? - { - for (unsigned int i = 0; i < height_; i++) - { - lineStatus_[i] = LINE_NOT_CHECKED; - } - } - - int foundChanges = 0; - - foundChanges = 0; - - int curIlace = interlace_[idxIlace]; - - bool moveBackward = false; - - logDebug("CorePoller::isChanged", "Interlace index [%d] interlace [%d].", idxIlace, curIlace); - - for (; curLine < (int) height_; curLine++) - { - logDebug("CorePoller::isChanged", "Analizing line [%d] move backward [%d] status [%d] priority [%d].", - curLine, moveBackward, lineStatus_[curIlace], linePriority_[curLine]); - - // - // Ask the caller if the polling have to be suspended. - // - - if ((*checkIfInputCallback)(arg) == 1) - { - *suspended = 1; - - break; - } - - // - // Suspend if too much time is elapsed. - // - - gettimeofday(&ts, NULL); - - newTime = ts.tv_sec * 1000 + ts.tv_usec / 1000; - - if (newTime - oldTime >= timeout) - { - *suspended = 1; - - break; - } - - oldTime = newTime; - - if (lineStatus_[curLine] != LINE_NOT_CHECKED) - { - continue; - } - - if (moveBackward) - { - moveBackward = false; - } - else - { - switch (linePriority_[curLine]) - { - case 1: - case 29: - { - // - // It was a priority, - // but now it may not be. - // - } - case 31: - { - // - // Not a priority, still isn't. - // - - linePriority_[curLine] = NOT_PRIORITY; - - break; - } - case 0: - { - // - // Make it a priority. - // - - linePriority_[curLine] = PRIORITY; - - break; - } - default: - { - linePriority_[curLine]--; - - break; - } - } - - if ((linePriority_[curLine] > PRIORITY) && ((curLine & 31) != curIlace)) - { - continue; - } - } - - XRectangle rect = {0, curLine, width_, 1}; - - char *buffer; - - logDebug("CorePoller::isChanged", "Checking line [%d].", curLine); - - if ((buffer = getRect(rect)) == NULL) - { - logDebug("CorePoller::isChanged", "Failed to retrieve line [%d].", curLine); - - return -1; - } - - if (memcmp(buffer, buffer_ + curLine * bpl_, bpl_) == 0 || differ(buffer, rect) == 0) - { - logDebug("CorePoller::isChanged", "Data buffer didn't change."); - - lineStatus_[curLine] = LINE_NOT_CHANGED; - - continue; - } - - rect.x = lefts_[rect.y]; - rect.width = rights_[rect.y] - lefts_[rect.y] + 1; - - update(buffer + rect.x * bpp_, rect); - - foundChanges = 1; - - lineStatus_[curLine] = LINE_HAS_CHANGED; - - // - // Wake up the next line. - // - - if (linePriority_[curLine + 1] > PRIORITY) - { - linePriority_[curLine + 1] = HIGHEST_PRIORITY; - } - - // - // Give this line priority. - // - - linePriority_[curLine] = HIGHEST_PRIORITY; - - // - // Wake up previous line. - // - - if (curLine > 0 && lineStatus_[curLine - 1] == LINE_NOT_CHECKED) - { - moveBackward = true; - curLine -= 2; - } - } - - // - // Execution reached the end of loop. - // - - if (curLine == (int) height_) - { - idxIlace = (idxIlace + 1) % 32; - - curLine = 0; - } - - // - // Create the region of changed pixels. - // - - if (foundChanges) - { - int start, last, curLine, left, right; - - for (curLine = 0; curLine < (int) height_; curLine++) - { - if (lineStatus_[curLine] == LINE_HAS_CHANGED) - { - break; - } - } - - start = curLine; - last = curLine; - - left = lefts_[curLine]; - right = rights_[curLine]; - curLine++; - - while (1) - { - for (; curLine < (int) height_; curLine++) - { - if (lineStatus_[curLine] == LINE_HAS_CHANGED) - { - break; - } - } - - if (curLine == (int) height_) - { - break; - } - - if ((curLine - last > minSliceHeight_) || (last - start > maxSliceHeight_)) - { - XRectangle rect = {left, start, right - left + 1, last - start + 1}; - - XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_); - - start = curLine; - left = lefts_[curLine]; - right = rights_[curLine]; - } - else - { - if (lefts_[curLine] < left) - { - left = lefts_[curLine]; - } - - if (rights_[curLine] > right) - { - right = rights_[curLine]; - } - } - - last = curLine; - - curLine++; - } - - // - // Send last block. - // - - if (last >= start) - { - XRectangle rect = {left, start, right - left + 1, last - start + 1}; - - XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_); - } - } - - return foundChanges; -} - -int CorePoller::differ(char *buffer, XRectangle r) -{ - logTrace("CorePoller::differ"); - - int bpl = bpp_ * r.width; - int i; - char *pBuf; - char *pFb; - - pBuf = (buffer); - pFb = (buffer_ + r.x + r.y * bpl_); - - for (i = 0; i < bpl; i++) - { - if (*pFb++ != *pBuf++) - { - lefts_[r.y] = i / bpp_; - - break; - } - } - - if (i == bpl) - { - return 0; - } - - pBuf = (buffer) + bpl - 1; - pFb = (buffer_ + r.x + r.y * bpl_) + bpl - 1; - - int j = i - 1; - - for (i = bpl - 1; i > j; i--) - { - if (*pFb-- != *pBuf--) - { - rights_[r.y] = i / bpp_; - - break; - } - } - - return 1; -} - -void CorePoller::update(char *src, XRectangle r) -{ - logTrace("CorePoller::update"); - - char *dst = buffer_ + r.x * bpp_ + r.y * bpl_; - int bpl = bpp_ * r.width; - - for (unsigned int i = 0; i < r.height; i++) - { - if(((r.x * bpp_ + r.y * bpl_) + bpl) > (bpl_ * height_)) - { - // - // Out of bounds. Maybe a resize is going on. - // - - continue; - } - - memcpy(dst, src, bpl); - - src += bpl; - - dst += bpl_; - } -} - -void CorePoller::handleEvent(Display *display, XEvent *event) -{ - logTrace("CorePoller::handleEvent"); - - switch (event -> type) - { - case KeyPress: - case KeyRelease: - { - handleKeyboardEvent(display, event); - break; - } - case ButtonPress: - case ButtonRelease: - case MotionNotify: - { - handleMouseEvent(display, event); - break; - } - default: - { - logTest("CorePoller::handleEvent", "Handling unexpected event [%d] from display [%p].", - event -> type, display); - break; - } - } -} - -void CorePoller::handleWebKeyEvent(KeySym keysym, Bool isKeyPress) -{ - logTrace("CorePoller::handleWebKeyEvent"); - - handleWebKeyboardEvent(keysym, isKeyPress); -} - -void CorePoller::handleInput() -{ - while (input_ -> checkIfEvent()) - { - Display *display = input_ -> currentDisplay(); - XEvent *event = input_ -> popEvent(); - - handleEvent(display, event); - - delete event; - } -} - -void CorePoller::createFrameBuffer() -{ - logTrace("CorePoller::createFrameBuffer"); - - if (buffer_ == NULL) - { - buffer_ = new char[bpl_ * height_]; - } -} diff --git a/nxcompshad/Core.h b/nxcompshad/Core.h deleted file mode 100644 index 91f3f1e22..000000000 --- a/nxcompshad/Core.h +++ /dev/null @@ -1,212 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef CorePoller_H -#define CorePoller_H - -#include - -#include "Logger.h" -#include "Regions.h" -#include "Input.h" - -typedef enum{ - LINE_HAS_CHANGED, - LINE_NOT_CHECKED, - LINE_NOT_CHANGED -} LineStatus; - -typedef enum{ - HIGHEST_PRIORITY = 0, - PRIORITY = 30, - NOT_PRIORITY = 90 -} LinePriority; - -class CorePoller -{ - public: - - CorePoller(Input*, Display*); - - virtual ~CorePoller(); - - virtual int init(); - - unsigned int width() const; - - unsigned int height() const; - - unsigned char depth() const; - - int isChanged(int (*)(void*), void *, int *); - - char *getFrameBuffer() const; - - void destroyFrameBuffer(); - - void createFrameBuffer(); - - Region lastUpdatedRegion(); - - Region getLastUpdatedRegion(); - - void handleInput(); - - void handleEvent(Display *, XEvent *); - - void handleWebKeyEvent(KeySym keysym, Bool isKeyPress); - - Display *getShadowDisplay(); - - void setShadowDisplay(Display *shadowDisplay); - - protected: - - unsigned int bpp_; - - unsigned int bpl_; - - unsigned int width_; - - unsigned int height_; - - int depth_; - - char *buffer_; - - unsigned long redMask_; - unsigned long greenMask_; - unsigned long blueMask_; - unsigned long colorMask_[3]; - - char mirror_; - - char mirrorChanges_; - - virtual int updateShadowFrameBuffer(void) = 0; - - virtual char *getRect(XRectangle r) = 0; - - int imageByteOrder_; - - #ifdef __CYGWIN32__ - virtual char checkDesktop(void) = 0; - #endif - - Display *shadowDisplay_; - - void update(char *src, XRectangle r); - - Region lastUpdatedRegion_; - - private: - - virtual void handleKeyboardEvent(Display *, XEvent *) = 0; - - virtual void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) = 0; - - virtual void handleMouseEvent(Display *, XEvent *) = 0; - - Input *input_; - - static const int maxSliceHeight_; - static const int minSliceHeight_; - - LineStatus *lineStatus_; - int *linePriority_; - - static const char interlace_[]; - - int *lefts_; - int *rights_; - - // FIXME: Make them friend. - - int differ(char *src, XRectangle r); -}; - -inline unsigned int CorePoller::width() const -{ - return width_; -} - -inline unsigned int CorePoller::height() const -{ - return height_; -} - -inline unsigned char CorePoller::depth() const -{ - return depth_; -} - -inline char *CorePoller::getFrameBuffer() const -{ - return buffer_; -} - -inline void CorePoller::destroyFrameBuffer() -{ - if (buffer_ != NULL) - { - delete[] buffer_; - buffer_ = NULL; - } -} - -inline Region CorePoller::lastUpdatedRegion() -{ - Region region = lastUpdatedRegion_; - - lastUpdatedRegion_ = XCreateRegion(); - - if (lastUpdatedRegion_ == NULL) - { - logError("CorePoller::lastUpdatedRegion", ESET(ENOMEM)); - - lastUpdatedRegion_ = region; - - return NULL; - } - - return region; -} - -inline Region CorePoller::getLastUpdatedRegion() -{ - return lastUpdatedRegion_; -} - -inline Display *CorePoller::getShadowDisplay() -{ - return shadowDisplay_ ; -} - -inline void CorePoller::setShadowDisplay(Display *shadowDisplay) -{ - shadowDisplay_ = shadowDisplay; -} - -#endif /* CorePoller_H */ diff --git a/nxcompshad/Input.cpp b/nxcompshad/Input.cpp deleted file mode 100644 index a79b30459..000000000 --- a/nxcompshad/Input.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include "Input.h" -#include "Logger.h" - -Input::Input() -{ - logTrace("Input::Input"); - - eventsHead_ = NULL; - eventsTail_ = NULL; - keymap_ = NULL; -} - -Input::~Input() -{ - logTrace("Input::~Input"); - - Event *head = eventsHead_; - - while (head) - { - Event *next = head -> next; - - delete head -> event; - delete head; - - head = next; - } - - if (keymap_ != NULL) - { - logDebug("Input::~Input", "Delete keymap_ [%p].", keymap_); - - delete [] keymap_; - } -} - -void Input::pushEvent(Display *display, XEvent *event) -{ - Event *tail = new Event; - - if (tail == NULL) - { - logError("Input::pushEvent", ESET(ENOMEM)); - - return; - } - - tail -> next = NULL; - tail -> display = display; - tail -> event = event; - - if (eventsHead_ == NULL) - { - eventsHead_ = tail; - } - else - { - eventsTail_ -> next = tail; - } - - eventsTail_ = tail; -} - -XEvent *Input::popEvent() -{ - Event *head = eventsHead_; - - if (head == NULL) - { - return 0; - } - - XEvent *event = head -> event; - - eventsHead_ = head -> next; - - delete head; - - if (eventsHead_ == NULL) - { - eventsTail_ = NULL; - } - - return event; -} - -int Input::removeAllEvents(Display *display) -{ - logTrace("Input::removeAllEvents"); - - int nRemoved = 0; - - Event *current = eventsHead_; - - while (current) - { - if (display == current -> display) - { - // - // Update head of list. - // - - if (current == eventsHead_) - { - eventsHead_ = current -> next; - } - - // - // Update tail of list. - // - - if (current == eventsTail_) - { - eventsTail_ = eventsHead_; - - while (eventsTail_ && eventsTail_ -> next) - { - eventsTail_ = eventsTail_ -> next; - } - } - - // - // Remove event. - // - - Event *next = current -> next; - - delete current -> event; - delete current; - - current = next; - - nRemoved++; - } - else - { - current = current -> next; - } - } - - return nRemoved; -} - diff --git a/nxcompshad/Input.h b/nxcompshad/Input.h deleted file mode 100644 index cbba029a9..000000000 --- a/nxcompshad/Input.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Input_H -#define Input_H - -#include - -typedef struct Event -{ - struct Event *next; - Display *display; - XEvent *event; -} Event; - -class Input -{ - public: - - Input(); - - ~Input(); - - int checkIfEvent(); - - void pushEvent(Display *, XEvent *); - - XEvent *popEvent(); - Display *currentDisplay(); - - int removeAllEvents(Display *); - - void setKeymap(char *keymap); - char *getKeymap(); - - void setShadowDisplayName(char *shadowDisplayName); - char *getShadowDisplayName(); - - private: - - Event *eventsHead_; - Event *eventsTail_; - char *keymap_; - char *shadowDisplayName_; -}; - -inline Display *Input::currentDisplay() -{ - return eventsHead_ ? eventsHead_ -> display : NULL; -} - -inline int Input::checkIfEvent() -{ - return (eventsHead_ != NULL); -} - -inline void Input::setKeymap(char *keymap) -{ - keymap_ = keymap; -} - -inline char *Input::getKeymap() -{ - return keymap_; -} - -inline void Input::setShadowDisplayName(char *shadowDisplayName) -{ - shadowDisplayName_ = shadowDisplayName; -} - -inline char *Input::getShadowDisplayName() -{ - return shadowDisplayName_; -} - -#endif /* Input_H */ diff --git a/nxcompshad/Logger.cpp b/nxcompshad/Logger.cpp deleted file mode 100644 index f27c97c19..000000000 --- a/nxcompshad/Logger.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include -#include -#include - -#define PANIC -#define WARNING -#undef TEST -#define DEBUG - -#include "Misc.h" -#include "Logger.h" - -Logger logger; - -void Logger::user(const char *format, va_list arguments) -{ - char string[1024]; - - vsnprintf(string, 1024, format, arguments); - - fprintf(stderr, "%s\n", string); -} - -void Logger::error(const char *name, int error) -{ - fprintf(stderr, "PANIC! %s: Failed with code %d: %s\n", - name, error, strerror(error)); -} - -void Logger::warning(const char *name, const char *format, va_list arguments) -{ - char string[1024]; - - vsnprintf(string, 1024, format, arguments); - - fprintf(stderr, "%s: WARNING! %s\n", name, string); -} - -void Logger::test(const char *name, const char *format, va_list arguments) -{ - char string[1024]; - - vsnprintf(string, 1024, format, arguments); - - fprintf(stderr, "%s: %s\n", name, string); -} - -void Logger::trace(const char *name) -{ - fprintf(stderr, "%s\n", name); -} - -void Logger::debug(const char *name, const char *format, va_list arguments) -{ - char string[1024]; - - vsnprintf(string, 1024, format, arguments); - - fprintf(stderr, "%s: %s\n", name, string); -} - -void Logger::dump(const char *name, const char *data, int size) -{ - fprintf(stderr, "%s: Dumping %d bytes of data at %p\n", - name, size, data); - - for (int i = 0; i < size;) - { - fprintf(stderr, "[%d]\t", i); - - int t = i; - - for (unsigned int ii = 0; i < size && ii < 8; i++, ii++) - { - fprintf(stderr, "%02x/%d\t", data[i] & 0xff, data[i]); - } - - for (unsigned int ii = i % 8; ii > 0 && ii < 8; ii++) - { - fprintf(stderr, "\t"); - } - - i = t; - - for (unsigned int ii = 0; i < size && ii < 8; i++, ii++) - { - if (isprint(data[i])) - { - fprintf(stderr, "%c", data[i]); - } - else - { - fprintf(stderr, "."); - } - } - - fprintf(stderr, "\n"); - } -} diff --git a/nxcompshad/Logger.h b/nxcompshad/Logger.h deleted file mode 100644 index eba81f642..000000000 --- a/nxcompshad/Logger.h +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Logger_H -#define Logger_H - -#include -#include - -// -// Error handling macros. -// - -#define ESET(e) (errno = (e)) -#define EGET() (errno) -#define ESTR() strerror(errno) - -extern class Logger logger; - -class Logger -{ - public: - - void user(const char *format, va_list arguments); - - void error(const char *name, int error); - - void warning(const char *name, const char *format, va_list arguments); - - void test(const char *name, const char *format, va_list arguments); - - void trace(const char *name); - - void debug(const char *name, const char *format, va_list arguments); - - void dump(const char *name, const char *data, int size); -}; - -static inline void logUser(const char *format, ...) \ - __attribute__((format(printf, 1, 2))) __attribute__((__unused__)); - -static inline void logError(const char *name, int error) \ - __attribute__((__unused__)); - -static inline void logWarning(const char *name, const char *format, ...) \ - __attribute__((__unused__)); - -static inline void logTest(const char *name, const char *format, ...) \ - __attribute__((format(printf, 2, 3))) __attribute__((__unused__)); - -static inline void logTrace(const char *name) \ - __attribute__((__unused__)); - -static inline void logDebug(const char *name, const char *format, ...) \ - __attribute__((format(printf, 2, 3))) __attribute__((__unused__)); - -static inline void logDump(const char *name, const char *data, int size) \ - __attribute__((__unused__)); - -static inline void logUser(const char *format, ...) -{ - va_list arguments; - - va_start(arguments, format); - - logger.user(format, arguments); - - va_end(arguments); -} - -static inline void logError(const char *name, int error) -{ - #if defined(DEBUG) || defined(TEST) || \ - defined(WARNING) || defined(PANIC) - - logger.error(name, error); - - #endif -} - -static inline void logWarning(const char *name, const char *format, ...) -{ - #if defined(DEBUG) || defined(TEST) || \ - defined(WARNING) - - va_list arguments; - - va_start(arguments, format); - - logger.warning(name, format, arguments); - - va_end(arguments); - - #endif -} - -static inline void logTest(const char *name, const char *format, ...) -{ - #if defined(TEST) - - va_list arguments; - - va_start(arguments, format); - - logger.test(name, format, arguments); - - va_end(arguments); - - #endif -} - -static inline void logTrace(const char *name) -{ - #if defined(DEBUG) - - logger.trace(name); - - #endif -} - -static inline void logDebug(const char *name, const char *format, ...) -{ - #if defined(DEBUG) - - va_list arguments; - - va_start(arguments, format); - - logger.debug(name, format, arguments); - - va_end(arguments); - - #endif -} - -static inline void logDump(const char *name, const char *data, int size) -{ - #if defined(TEST) - - logger.dump(name, data, size); - - #endif -} - -#endif /* Logger_H */ diff --git a/nxcompshad/Makefile.am b/nxcompshad/Makefile.am new file mode 100644 index 000000000..f3666a08a --- /dev/null +++ b/nxcompshad/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = src + +pkgconfig_DATA = nxcompshad.pc + +MAINTAINERCLEANFILES = \ + $(srcdir)/autom4te.cache/* \ + $(srcdir)/build-aux/* \ + $(srcdir)/Makefile.in \ + $(srcdir)/src/Makefile.in \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/config.h.in \ + $(srcdir)/config.h.in~ \ + $(srcdir)/configure \ + $(srcdir)/m4/libtool.m4 \ + $(srcdir)/m4/lt~obsolete.m4 \ + $(srcdir)/m4/ltoptions.m4 \ + $(srcdir)/m4/ltsugar.m4 \ + $(srcdir)/m4/ltversion.m4 \ + $(NULL) + +DISTCLEANFILES=$(MAINTAINERCLEANFILES) diff --git a/nxcompshad/Makefile.in b/nxcompshad/Makefile.in deleted file mode 100644 index 34b785d25..000000000 --- a/nxcompshad/Makefile.in +++ /dev/null @@ -1,251 +0,0 @@ -#/**************************************************************************/ -#/* */ -#/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -#/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -#/* Copyright (c) 2014-2016 Ulrich Sibiller */ -#/* Copyright (c) 2014-2016 Mihai Moldovan */ -#/* Copyright (c) 2011-2016 Mike Gabriel */ -#/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -#/* */ -#/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -#/* are copyright of the aforementioned persons and companies. */ -#/* */ -#/* Redistribution and use of the present software is allowed according */ -#/* to terms specified in the file LICENSE which comes in the source */ -#/* distribution. */ -#/* */ -#/* All rights reserved. */ -#/* */ -#/* NOTE: This software has received contributions from various other */ -#/* contributors, only the core maintainers and supporters are listed as */ -#/* copyright holders. Please contact us, if you feel you should be listed */ -#/* as copyright holder, as well. */ -#/* */ -#/**************************************************************************/ - -# -# Get values from configure script. -# - -VERSION=@VERSION@ -LIBVERSION=@LIBVERSION@ - -# -# We would really like to enable all warnings, -Wredundant-decls, -# though, gives a warning caused by pthread.h and unistd.h and -# GCC 3.4 was changed in a way that it now complains about some -# of the -W directives we used before (-Wmissing-declarations, -# -Wnested-externs, -Wstrict-prototypes and -Wmissing-prototypes). -# - -CXX = @CXX@ -CXXFLAGS = @CXXFLAGS@ @X_CFLAGS@ @DEFS@ \ - -Wall -Wpointer-arith -CXXINCLUDES = -CXXDEFINES = - -CPPFLAGS = @CPPFLAGS@ - -# -# C programs don't share the C++ flags. They should -# have their own @CCFLAGS@. -# - -CC = @CC@ -CCFLAGS = @X_CFLAGS@ @DEFS@ \ - -Wall -Wpointer-arith -CCINCLUDES = -CCDEFINES = - -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -lNX_X11 - -# -# Only if THREADS is defined. -# -# LIBS = $(LIBS) -lpthread -# - -# -# Only if you want ElectricFence. -# -# LIBS = $(LIBS) -lefence -# - -# -# Only if you want mpatrol. -# -# LIBS = $(LIBS) -lmpatrol -lbfd -liberty -# - -srcdir = @srcdir@ -prefix = @prefix@ -datarootdir = @datarootdir@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -man1dir = @mandir@/man1 -VPATH = @srcdir@ -libdir = @libdir@ -includedir = @includedir@ -pkgconfigdir = @pkgconfigdir@ - -INSTALL = @INSTALL@ -INSTALL_DIR = $(INSTALL) -d -m 0755 -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_LINK = cp -av -DESTDIR = -RM_FILE = rm -f -RM_DIR = rmdir -p --ignore-fail-on-non-empty - -# -# This should be autodetected. -# - -MAKEDEPEND = @MAKEDEPEND@ -DEPENDINCLUDES = -I/usr/include/g++ -I/usr/include/g++-3 - -.SUFFIXES: .cpp.c - -.cpp.o: - $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $(CXXINCLUDES) $(CXXDEFINES) $< -.c.o: - $(CC) -c $(CPPFLAGS) $(CCFLAGS) $(CCINCLUDES) $(CCDEFINES) $< - -LIBRARY = Xcompshad - -LIBNAME = lib$(LIBRARY) -ifeq ($(shell uname),Darwin) -LIBFULL = lib$(LIBRARY).$(VERSION).dylib -LIBLOAD = lib$(LIBRARY).$(LIBVERSION).dylib -LIBSHARED = lib$(LIBRARY).dylib -COMP_VER = $(shell echo '$(VERSION)' | cut -d '.' -f 1-3) -LIBFLAGS = -install_name $(libdir)/$(LIBLOAD) -compatibility_version $(LIBVERSION) -current_version $(COMP_VER) -else -LIBFULL = lib$(LIBRARY).so.$(VERSION) -LIBLOAD = lib$(LIBRARY).so.$(LIBVERSION) -LIBSHARED = lib$(LIBRARY).so -LIBFLAGS = -endif -LIBARCHIVE = lib$(LIBRARY).a - -MSRC = Main.c - -CSRC = - -CXXSRC = Core.cpp \ - Input.cpp \ - Logger.cpp \ - Shadow.cpp \ - X11.cpp \ - Win.cpp \ - Updater.cpp \ - Manager.cpp - -MOBJ = $(MSRC:.c.cpp=.o) -COBJ = $(CSRC:.c=.o) -CXXOBJ = $(CXXSRC:.cpp=.o) - -MLIBS = -L. -lXShadow - -ifeq ($(findstring -lgdi32,$(LIBS)),-lgdi32) - -# We need a smarter way to detect windows -# platform. - -LIBDLL = cyg$(LIBRARY).dll -LIBDLLSTATIC = lib${LIBRARY}.dll.a - -all: depend $(LIBARCHIVE) $(LIBDLL) - -else - -EXTRALIBS = -lXext -lXtst -lXrandr -lXdamage - -all: depend $(LIBFULL) $(LIBLOAD) $(LIBSHARED) $(LIBARCHIVE) - -endif - -$(LIBFULL): $(CXXOBJ) $(COBJ) - $(CXX) -o $@ $(LDFLAGS) $(LIBFLAGS) $(CXXOBJ) $(COBJ) $(LIBS) $(EXTRALIBS) - -$(LIBLOAD): $(LIBFULL) - rm -f $(LIBLOAD) - ln -s $(LIBFULL) $(LIBLOAD) - -$(LIBSHARED): $(LIBFULL) - rm -f $(LIBSHARED) - ln -s $(LIBFULL) $(LIBSHARED) - -$(LIBARCHIVE): $(CXXOBJ) $(COBJ) - rm -f $(LIBARCHIVE) - ar clq $(LIBARCHIVE) $(CXXOBJ) $(COBJ) - ranlib $(LIBARCHIVE) - -$(LIBDLL): $(LIBARCHIVE) - $(CC) -o $@ \ - -shared \ - -Wl,--out-implib=$(LIBDLLSTATIC) \ - -Wl,--export-all-symbols \ - -Wl,--enable-auto-import \ - -Wl,--whole-archive ${LIBARCHIVE} \ - -Wl,--no-whole-archive \ - ${LIBS} - -$(PROGRAM): $(MOBJ) $(COBJ) $(CXXOBJ) $(LIBDLL) -# $(CC) $(CCFLAGS) -o $@ $(MOBJ) $(MLIBS) - -depends: depend.status - -depend: depend.status - -depend.status: - if [ -n "$(MAKEDEPEND)" ] && [ -x "$(MAKEDEPEND)" ] ; then \ - $(MAKEDEPEND) $(CXXINCLUDES) $(CCINCLUDES) \ - $(DEPENDINCLUDES) -f Makefile $(MSRC) $(CSRC) $(CXXSRC) 2>/dev/null; \ - fi - touch depend.status - -install: install.bin install.lib install.man - -install.bin: - -install.lib: all - $(INSTALL_DIR) $(DESTDIR)${libdir} - $(INSTALL_DIR) $(DESTDIR)${pkgconfigdir} - $(INSTALL_DIR) $(DESTDIR)${includedir}/nx - $(INSTALL_DIR) $(DESTDIR)${pkgconfigdir} - $(INSTALL_DATA) $(LIBFULL) $(DESTDIR)${libdir} - $(INSTALL_LINK) $(LIBLOAD) $(DESTDIR)${libdir} - $(INSTALL_LINK) $(LIBSHARED) $(DESTDIR)${libdir} - $(INSTALL_DATA) $(LIBARCHIVE) $(DESTDIR)${libdir} - $(INSTALL_DATA) Shadow.h $(DESTDIR)${includedir}/nx - $(INSTALL_DATA) nxcompshad.pc $(DESTDIR)${pkgconfigdir} - echo "Running ldconfig tool, this may take a while..." && ldconfig || true - -install.man: - -uninstall: uninstall.bin uninstall.lib uninstall.man - -uninstall.bin: - -uninstall.lib: - $(RM_FILE) $(DESTDIR)${libdir}/$(LIBFULL) - $(RM_FILE) $(DESTDIR)${libdir}/$(LIBLOAD) - $(RM_FILE) $(DESTDIR)${libdir}/$(LIBSHARED) - $(RM_FILE) $(DESTDIR)${libdir}/$(LIBARCHIVE) - for header in *.h; do $(RM_FILE) $(DESTDIR)${includedir}/nx/$$header; done - $(RM_DIR) $(DESTDIR)${libdir}/nx/ - $(RM_DIR) $(DESTDIR)${includedir}/nx/ - $(RM_FILE) $(DESTDIR)${pkgconfigdir}/nxcompshad.pc - echo "Running ldconfig tool, this may take a while..." && ldconfig || true - -uninstall.man: - -clean: - -rm -f *~ *.o *.gch *.bak st?????? core core.* *.out.* *.exe.stackdump *.pc \ - $(LIBFULL) $(LIBLOAD) $(LIBSHARED) $(LIBARCHIVE) $(LIBDLL) $(LIBDLLSTATIC) $(PROGRAM) $(PROGRAM).exe - -distclean: clean - -rm -rf config.status config.log config.cache depend.status Makefile tags autom4te.cache configure diff --git a/nxcompshad/Manager.cpp b/nxcompshad/Manager.cpp deleted file mode 100644 index 3bb36c13f..000000000 --- a/nxcompshad/Manager.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include -#include -#include -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include "Manager.h" -#include "Logger.h" - -UpdateManager::UpdateManager(int w, int h, char *f, Input *i) - : width_(w), height_(h), frameBuffer_(f), input_(i) -{ - logTrace("UpdateManager::UpdateManager"); - - nUpdater = 0; - updaterVector = NULL; - updateManagerRegion_ = NULL; -} - -UpdateManager::~UpdateManager() -{ - logTrace("UpdateManager::~UpdateManager"); - - for (int i = 0; i < nUpdater; i++) - { - delete updaterVector[i]; - } - - delete [] updaterVector; -} - -Updater *UpdateManager::createUpdater(char *displayName, Display *display) -{ - Updater *updater = new Updater(displayName, display); - - if (updater == NULL) - { - logError("UpdateManager::createUpdater", ESET(ENOMEM)); - - return NULL; - } - - if (updater -> init(width_, height_, frameBuffer_, input_) == -1) - { - logError("UpdateManager::createUpdater", EGET()); - - delete updater; - - return NULL; - } - - return updater; -} - -UpdaterHandle UpdateManager::addUpdater(char *displayName, Display *display) -{ - Updater *newUpdater = createUpdater(displayName, display); - - if (newUpdater == NULL) - { - logError("UpdateManager::addUpdater", EGET()); - - return NULL; - } - - Updater **newUpdaterVector = new Updater*[nUpdater + 1]; - - if (newUpdaterVector == NULL) - { - logError("UpdateManager::addUpdater", ESET(ENOMEM)); - - delete newUpdater; - - return NULL; - } - - for (int i = 0; i < nUpdater; i++) - { - newUpdaterVector[i] = updaterVector[i]; - } - - newUpdaterVector[nUpdater] = newUpdater; - - delete [] updaterVector; - - updaterVector = newUpdaterVector; - - nUpdater++; - - logTest("UpdateManager::AddUpdater", "Number of updaters [%d].", nUpdater); - - return reinterpret_cast(newUpdater); -} - -int UpdateManager::removeAllUpdaters() -{ - logTest("UpdateManager::removeAllUpdaters", "Number of updaters [%d].", nUpdater); - - int nullUpdaters = 0; - - for (int i = nUpdater; i > 0; i--) - { - if (removeUpdater(reinterpret_cast(updaterVector[i - 1])) == 0) - { - nullUpdaters++; - } - } - - if (nUpdater == 0) - { - return 1; - } - - if (nUpdater == nullUpdaters) - { - logTest("UpdateManager::removeAllUpdaters", "Ignored null records in Updater vector."); - - return 0; - } - - logTest("UpdateManager::removeAllUpdaters", "Failed to remove some updaters."); - - return -1; -} - -int UpdateManager::removeUpdater(UpdaterHandle handle) -{ - Updater * const updater = (Updater*) handle; - - logTest("UpdateManager::removeUpdater", "Removing Updater [%p].", updater); - - if (updater == NULL) - { - return 0; - } - - for (int i = 0; i < nUpdater; i++) - { - if (updater == updaterVector[i]) - { - updaterVector[i] = updaterVector[nUpdater - 1]; - - nUpdater--; - - delete updater; - - return 1; - } - } - - logTest("UpdateManager::removeUpdater", "Couldn't find Updater [%p].", updater); - - return -1; -} - -void UpdateManager::addRegion(Region region) -{ - logTrace("UpdateManager::addRegion"); - - for (int i = 0; i < nUpdater; i++) - { - updaterVector[i] -> addRegion(region); - } - - XDestroyRegion(region); -} - -void UpdateManager::update() -{ - logTrace("UpdateManager::update"); - - for (int i = 0; i < nUpdater; i++) - { - /*updaterVector[i] -> update();*/ - if (updaterVector[i] -> getUpdateRegion()) - { - logDebug("UpdateManager::update", "pRegion [%p] rect[%ld].", - updaterVector[i] -> getUpdateRegion(), (updaterVector[i] -> getUpdateRegion()) -> numRects); - - updateManagerRegion_ = updaterVector[i] -> getUpdateRegion(); - // - // FIXME: Remove me. - // - for (int j = 0; j < updateManagerRegion_ -> numRects; j++) - { - int x = updateManagerRegion_ -> rects[j].x1; - int y = updateManagerRegion_ -> rects[j].y1; - unsigned int width = updateManagerRegion_ -> rects[j].x2 - updateManagerRegion_ -> rects[j].x1; - unsigned int height = updateManagerRegion_ -> rects[j].y2 - updateManagerRegion_ -> rects[j].y1; - logDebug("UpdateManager::update", "x[%d]y[%d]width[%u]height[%u], updateManagerRegion_[%p]", - x, y, width, height, updateManagerRegion_); - } - } - } -} - -void UpdateManager::handleInput() -{ - logTrace("UpdateManager::handleInput"); - - for (int i = 0; i < nUpdater; i++) - { - try - { - updaterVector[i] -> handleInput(); - } - catch (UpdaterClosing u) - { - logTest("UpdateManager::handleInput", "Catched exception UpdaterClosing()."); - - removeUpdater((UpdaterHandle)updaterVector[i]); - - // - // Now the i-element of the updaterVector - // is changed. We don't want to skip it. - // - - i--; - } - } -} - -void UpdateManager::newRegion() -{ - logTrace("UpdateManager::newRegion"); - - for (int i = 0; i < nUpdater; i++) - { - updaterVector[i] -> newRegion(); - } -} diff --git a/nxcompshad/Manager.h b/nxcompshad/Manager.h deleted file mode 100644 index 92a82cd32..000000000 --- a/nxcompshad/Manager.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef UpdateManager_H -#define UpdateManager_H - -#include - -#include "Updater.h" -#include "Regions.h" -#include "Input.h" - -typedef char* UpdaterHandle; - -class UpdateManager -{ - public: - - UpdateManager(int, int, char *, Input *); - - ~UpdateManager(); - - void handleInput(); - - void addRegion(Region); - - void update(); - - UpdaterHandle addUpdater(char *displayName, Display *display); - - int removeUpdater(UpdaterHandle); - - int removeAllUpdaters(); - - int numberOfUpdaters(); - - int getWidth(); - - int getHeight(); - - char *getBuffer(); - - Region getUpdateManagerRegion(); - - void destroyUpdateManagerRegion(); - - void newRegion(); - - private: - - Updater *createUpdater(char *displayName, Display *display); - - int width_; - int height_; - char *frameBuffer_; - Input *input_; - - int nUpdater; - - Updater **updaterVector; - - Region updateManagerRegion_; - -}; - -inline int UpdateManager::numberOfUpdaters() -{ - return nUpdater; -} - -inline int UpdateManager::getWidth() -{ - return width_; -} - -inline int UpdateManager::getHeight() -{ - return height_; -} - -inline char *UpdateManager::getBuffer() -{ - return frameBuffer_; -} - -inline Region UpdateManager::getUpdateManagerRegion() -{ - return updateManagerRegion_; -} - -inline void UpdateManager::destroyUpdateManagerRegion() -{ - if (updateManagerRegion_ != NULL) - { - XDestroyRegion(updateManagerRegion_); - - updateManagerRegion_ = NULL; - } -} - -#endif /* UpdateManager_H */ diff --git a/nxcompshad/Misc.h b/nxcompshad/Misc.h deleted file mode 100644 index 9386dc080..000000000 --- a/nxcompshad/Misc.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Misc_H -#define Misc_H - -#include - -#include -#include - -using namespace std; - -// -// Error handling macros. -// - -#define ESET(e) (errno = (e)) -#define EGET() (errno) -#define ESTR() strerror(errno) - -// -// Log file. -// - -extern ostream *logofs; - -#endif /* Misc_H */ diff --git a/nxcompshad/Poller.h b/nxcompshad/Poller.h deleted file mode 100644 index 6236f872f..000000000 --- a/nxcompshad/Poller.h +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Poller_H -#define Poller_H - -#if defined(__CYGWIN32__) || defined(WIN32) - -#include "Win.h" - -#else - -#include "X11.h" - -#endif - -#endif /* Poller_H */ diff --git a/nxcompshad/Regions.h b/nxcompshad/Regions.h deleted file mode 100644 index 59fdcb46c..000000000 --- a/nxcompshad/Regions.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Region_H -#define Region_H - -#include -#include - -typedef struct { - short x1, x2, y1, y2; -} Box, BOX, BoxRec, *BoxPtr; - -typedef struct _XRegion { - long size; - long numRects; - BOX *rects; - BOX extents; -}; - -#endif /* Region_H */ diff --git a/nxcompshad/Shadow.cpp b/nxcompshad/Shadow.cpp deleted file mode 100644 index 643a5a807..000000000 --- a/nxcompshad/Shadow.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include "Logger.h" -#include "Shadow.h" -#include "Poller.h" -#include "Manager.h" - -typedef struct { - KeySym *map; - KeyCode minKeyCode, - maxKeyCode; - int mapWidth; -} KeySymsRec, *KeySymsPtr; - -KeySymsPtr NXShadowKeymap = NULL; - -ShadowOptions NXShadowOptions = {1, 1, -1}; - -static int mirrorException = 0; - -static UpdateManager *updateManager; -static Poller *poller; -static Input *input; - -int NXShadowRemoveAllUpdaters(); - -inline bool NXShadowNotInitialized() -{ - // - // updateManager depends on input and poller. - // So this test seem redundant. - // - // return (input == NULL) || (poller == NULL) || (updateManager == NULL); - // - - return (updateManager == NULL); -} - -#ifdef NEED_SIGNAL_HANDLER -static void NXSignalHandler(int signal) -{ - logTest("NXSignalHandler", "Got signal [%d]", signal); - - if (signal == SIGINT) - { - mirrorException = 1; - } - else if (signal == SIGTERM) - { - mirrorException = 1; - } -} - -static int NXInitSignal() -{ - logTrace("NXInitSignal"); - - struct sigaction sa; - - sa.sa_handler = NXSignalHandler; - sigfillset(&sa.sa_mask); - sa.sa_flags = 0; - - int res; - - while ((res = sigaction(SIGINT, &sa, NULL)) == -1 && - errno == EINTR); - - if (res == -1) - { - logError("NXInitSignal", EGET()); - - return -1; - } - - return 1; -} -#endif - -static void NXHandleException() -{ - if (mirrorException) - { - mirrorException = 0; - - NXShadowRemoveAllUpdaters(); - } -} - -static int NXCreateInput(char *keymap, char *shadowDisplayName) -{ - logTrace("NXCreateInput"); - - input = new Input; - - if (input == NULL) - { - logError("NXCreateInput", ESET(ENOMEM)); - - return -1; - } - - input -> setKeymap(keymap); - - input -> setShadowDisplayName(shadowDisplayName); - - return 1; -} - -static int NXCreatePoller(Display *display, Display **shadowDisplay) -{ - logTrace("NXCreatePoller"); - - if (input == NULL) - { - logError("NXCreatePoller", ESET(EBADF)); - - return -1; - } - - poller = new Poller(input,display); - - if (poller == NULL) - { - logError("NXCreatePoller", ESET(ENOMEM)); - - return -1; - } - - if (poller -> init() == -1) - { - logWarning("NXCreatePoller", "Failed to initialize poller."); - - return -1; - } - - *shadowDisplay = poller -> getShadowDisplay(); - - logTest("NXCreatePoller", "Poller geometry [%d, %d], ShadowDisplay[%p].", poller -> width(), - poller -> height(), (Display *) *shadowDisplay); - - return 1; -} - -static int NXCreateUpdateManager() -{ - logTrace("NXCreateUpdateManager"); - - if (input == NULL || poller == NULL) - { - logError("NXCreateUpdateManager", ESET(EBADF)); - - return -1; - } - - updateManager = new UpdateManager(poller -> width(), poller -> height(), - poller -> getFrameBuffer(), input); - - if (updateManager == NULL) - { - logError("NXCreateUpdateManager", ESET(ENOMEM)); - - return -1; - } - - return 1; -} - -void NXShadowResetOptions() -{ - NXShadowOptions.optionShmExtension = 1; - NXShadowOptions.optionDamageExtension = 1; -} - -// -// Exported functions. -// - -int NXShadowHasUpdaters() -{ - logTrace("NXShadowHasUpdaters"); - - return (updateManager && updateManager -> numberOfUpdaters()) ? 1 : 0; -} - -int NXShadowRemoveAllUpdaters() -{ - logTrace("NXShadowRemoveAllUpdaters"); - - return updateManager ? updateManager -> removeAllUpdaters() : 0; -} - -int NXShadowRemoveUpdater(UpdaterHandle handle) -{ - logTrace("NXShadowRemoveUpdater"); - - return updateManager ? updateManager -> removeUpdater(handle) : 0; -} - -UpdaterHandle NXShadowAddUpdater(char *displayName) -{ - logTrace("NXShadowAddUpdater"); - - return updateManager ? updateManager -> addUpdater(displayName, NULL) : NULL; -} - -int NXShadowAddUpdaterDisplay(void *dpy, int *w, int *h, unsigned char *d) -{ - Display *display = reinterpret_cast(dpy); - - logTrace("NXShadowAddUpdaterDisplay"); - - if ((updateManager ? updateManager -> addUpdater(NULL, display) : NULL) == NULL) - { - logTest("NXShadowAddUpdaterDisplay", "Error"); - - return 0; - } - - *w = updateManager -> getWidth(); - *h = updateManager -> getHeight(); - *d = poller -> depth(); - - return 1; -} - -int NXShadowCreate(void *dpy, char *keymap, char* shadowDisplayName, void **shadowDpy) -{ - logTrace("NXShadowCreate"); - - Display *display = reinterpret_cast(dpy); - Display **shadowDisplay = reinterpret_cast(shadowDpy); - -/* if (NXInitSignal() != 1) - { - logError("NXShadowCreate", EGET()); - - return -1; - }*/ - - if (NXCreateInput(keymap, shadowDisplayName) != 1) - { - logError("NXShadowCreate", EGET()); - - return -1; - } - - if (NXCreatePoller(display, shadowDisplay) != 1) - { - logWarning("NXShadowCreate", "NXCreatePoller failed."); - - return -1; - } - - if (NXCreateUpdateManager() != 1) - { - logError("NXShadowCreate", EGET()); - - return -1; - } - - return 1; -} - -#if !defined(__CYGWIN32__) && !defined(WIN32) - -void NXShadowSetDisplayUid(int uid) -{ - NXShadowOptions.optionShadowDisplayUid = uid; -} - -void NXShadowDisableShm(void) -{ - logUser("NXShadowDisableShm: Disabling SHM.\n"); - - NXShadowOptions.optionShmExtension = 0; -} - -void NXShadowDisableDamage(void) -{ - NXShadowOptions.optionDamageExtension = 0; -} - -void NXShadowGetScreenSize(int *w, int *h) -{ - poller -> getScreenSize(w, h); -} - -void NXShadowSetScreenSize(int *w, int *h) -{ - poller -> setScreenSize(w, h); -} - -#endif - -void NXShadowDestroy() -{ - if (poller) - { - delete poller; - - poller = NULL; - } - - if (updateManager) - { - delete updateManager; - - updateManager = NULL; - } - - if (input) - { - delete input; - - input = NULL; - } -} - -void NXShadowHandleInput() -{ - logTrace("NXShadowHandleInput"); - - if (NXShadowNotInitialized()) - { - logError("NXShadowHandleInput - NXShadow not properly initialized.", ESET(EBADF)); - - return; - } - - NXHandleException(); - - updateManager -> handleInput(); - - poller -> handleInput(); -} - -int NXShadowHasChanged(int (*callback)(void *), void *arg, int *suspended) -{ - int result; - - logTrace("NXShadowHasChanged"); - - if (NXShadowNotInitialized()) - { - logError("NXShadowHasChanged - NXShadow not properly initialized.", ESET(EBADF)); - - return -1; - } - - // - // FIXME - //updateManager -> destroyUpdateManagerRegion(); - // - - updateManager -> newRegion(); - -#if !defined(__CYGWIN32__) && !defined(WIN32) - poller -> getEvents(); -#endif - - result = poller -> isChanged(callback, arg, suspended); - - if (result == 1) - { - updateManager -> addRegion(poller -> lastUpdatedRegion()); - - return 1; - } - else if (result == -1) - { - logTest("NXShadowHasChanged", "Scanline error."); - return -1; - } - - return 0; -} - -void NXShadowExportChanges(long *numRects, char **pBox) -{ - Region pReg; - - logTrace("NXShadowExportChanges"); - - if (NXShadowNotInitialized()) - { - logError("NXShadowExportChanges - NXShadow not properly initialized.", ESET(EBADF)); - } - - updateManager -> update(); - pReg = updateManager -> getUpdateManagerRegion(); - *numRects = pReg -> numRects; - *pBox = (char *)pReg -> rects; - - logTest("NXShadowExportChanges", "numRects [%ld] pBox[%p], pReg->numRects[%ld], rects[%p], size[%lu]", - *numRects, *pBox, pReg -> numRects, &(pReg -> rects -> x2), - (unsigned long) sizeof(pReg -> rects -> x2)); -} - -void NXShadowEvent(Display *display, XEvent event) -{ - poller -> handleEvent(display, &event); -} - -void NXShadowWebKeyEvent(KeySym keysym, Bool isKeyPress) -{ - poller -> handleWebKeyEvent(keysym, isKeyPress); -} - -#ifdef __CYGWIN32__ - -int NXShadowCaptureCursor(unsigned int wnd, void *vis) -{ - Window window = (Window)wnd; - Visual *visual = reinterpret_cast(vis); - - logTrace("NXShadowCaptureCursor"); - - logTest("NXShadowCaptureCursor","Init"); - - return poller -> updateCursor(window, visual); -} - -#endif - -void NXShadowUpdateBuffer(void **buffer) -{ - char **fBuffer = reinterpret_cast(buffer); - - if (*fBuffer != NULL) - { - poller -> destroyFrameBuffer(); - - poller -> init(); - } - - *fBuffer = poller -> getFrameBuffer(); - - logTest("NXShadowUpdateBuffer","New frame buffer [0x%p]", (void *)*fBuffer); -} - -void NXShadowInitKeymap(void *keysyms) -{ - NXShadowKeymap = (KeySymsPtr) keysyms; - - logTest("NXShadowInitKeymap","KeySyms pointer [0x%p]", (void *)NXShadowKeymap); -} diff --git a/nxcompshad/Shadow.h b/nxcompshad/Shadow.h deleted file mode 100644 index e1c57c432..000000000 --- a/nxcompshad/Shadow.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Shadow_H -#define Shadow_H - -#include - -#define NXShadowCorrectColor(length, buffer) \ -\ -{ \ - unsigned short a; \ - unsigned short b; \ - unsigned short *shorts; \ - int i; \ -\ - length >>= 1; \ - shorts = (unsigned short *)buffer; \ - for (i = 0; i < length ; i++) \ - { \ - a = shorts[i]; \ -\ - b = a & 63; \ - a <<= 1; \ - a = (a & ~127) | b; \ -\ - shorts[i] = a; \ - } \ -} - -#ifdef __cplusplus -extern "C" { -#endif - -typedef char* UpdaterHandle; - -typedef struct _ShadowOptions -{ - char optionShmExtension; - char optionDamageExtension; - int optionShadowDisplayUid; -} ShadowOptions; - -extern ShadowOptions NXShadowOptions; - -extern int NXShadowCreate(void *, char *, char *, void **); -extern void NXShadowDestroy(void); - -/* - * Use an already opened Display connection. - * We use instead of to avoid - * useless dependences from Xlib headers. - */ - -extern int NXShadowAddUpdaterDisplay(void *display, int *width, int *height, - unsigned char *depth); -extern UpdaterHandle NXShadowAddUpdater(char *displayName); -extern int NXShadowRemoveUpdater(UpdaterHandle handle); -extern int NXShadowRemoveAllUpdaters(void); - -extern void NXShadowHandleInput(void); -extern int NXShadowHasChanged(int (*)(void *), void *, int *); -extern void NXShadowExportChanges(long *, char **); -extern int NXShadowHasUpdaters(void); -extern int NXShadowCaptureCursor(unsigned int wnd, void *vis); -extern void NXShadowColorCorrect(int, int, unsigned int, unsigned int, char *); -extern void NXShadowUpdateBuffer(void **); - -extern void NXShadowEvent(Display *, XEvent); -extern void NXShadowWebKeyEvent(KeySym keysym, Bool isKeyPress); - -extern void NXShadowSetDisplayUid(int uid); - -extern void NXShadowDisableShm(void); -extern void NXShadowDisableDamage(void); - -extern void NXShadowGetScreenSize(int *width, int *height); -extern void NXShadowSetScreenSize(int *width, int *height); - -extern void NXShadowInitKeymap(void *keysyms); - -#ifdef __cplusplus -} -#endif - -#endif /* Shadow_H */ - diff --git a/nxcompshad/Updater.cpp b/nxcompshad/Updater.cpp deleted file mode 100644 index 67f4f9628..000000000 --- a/nxcompshad/Updater.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#include -#include -#include -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG -// -#include -// -#include "Updater.h" -#include "Logger.h" - -Updater::Updater(char *displayName, Display *display) -{ - logTrace("Updater::Updater"); - - displayName_ = displayName; - display_ = display; - closeDisplay_ = false; - image_ = NULL; - updateRegion_ = NULL; - buffer_ = NULL; -} - -Updater::~Updater() -{ - logTrace("Updater::~Updater"); - - if (input_) - { - int removedEvents = input_ -> removeAllEvents(display_); - - logTest("Updater::~Updater", "Removed events in input queue is [%d].", removedEvents); - } - - if (display_) - { - XDestroyWindow(display_, window_); - XFreePixmap(display_, pixmap_); - - if (closeDisplay_) - { - XCloseDisplay(display_); - } - } - - if (image_) - { - image_ -> data = NULL; - - XDestroyImage(image_); - } - - if (updateRegion_) - { - XDestroyRegion(updateRegion_); - } -} - -int Updater::init(int width, int height, char *fb, Input *input) -{ - logTrace("Updater::init"); - - if (fb == NULL || input == NULL || width <= 0 || height <= 0) - { - logError("Updater::init", ESET(EINVAL)); - - return -1; - } - - width_ = width; - height_ = height; - buffer_ = fb; - input_ = input; -/* - if (display_ == NULL) - { - display_ = XOpenDisplay(displayName_); - - closeDisplay_ = true; - - if (display_ == NULL) - { - logError("Updater::init", ESET(ENOMSG)); - - return -1; - } - } -*/ - depth_ = DefaultDepth(display_, DefaultScreen(display_)); - - if (depth_ == 8) bpl_ = width_; - else if (depth_ == 16) bpl_ = width_ * 2; - else bpl_ = width_ * 4; - - logTest("Updater::init", "Server geometry [%d, %d] depth [%d] bpl [%d].", width_, height_, depth_, bpl_); - -/* int bitmap_pad = 8; - - image_ = XCreateImage(display_, DefaultVisual(display_, DefaultScreen(display_)), depth_, ZPixmap, 0, - buffer_, width_, height_, bitmap_pad, 0); - - if (image_ == NULL) - { - logError("Updater::init", ESET(ENOMSG)); - - logTest("Updater::init", "Failed to create default image."); - - return -1; - } - - pixmap_ = XCreatePixmap(display_, DefaultRootWindow(display_), width_, height_, depth_); - - unsigned int mask = CWBackPixmap | CWBorderPixel | CWEventMask; - - XSetWindowAttributes attributes; - - attributes.background_pixmap = pixmap_; - attributes.border_pixel = WhitePixel(display_, DefaultScreen(display_)); - attributes.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; - - window_ = XCreateWindow(display_, DefaultRootWindow(display_), - 0, 0, width_, height_, 0, depth_, InputOutput, - DefaultVisual(display_, DefaultScreen(display_)), mask, &attributes); - - if (window_ == None) - { - logError("Updater::init", ESET(ENOMSG)); - - return -1; - } - - XSizeHints *size_hints; - - if ((size_hints = XAllocSizeHints()) == NULL) - { - logError("Updater::init", ESET(ENOMEM)); - - return -1; - } - - size_hints -> flags = PMinSize | PMaxSize; - size_hints -> min_width = width_; - size_hints -> max_width = width_; - size_hints -> min_height = height_; - size_hints -> max_height = height_; - - XSetWMNormalHints(display_, window_, size_hints); - - XFree(size_hints); - - Atom deleteWMatom = XInternAtom(display_, "WM_DELETE_WINDOW", 1); - - XSetWMProtocols(display_, window_, &deleteWMatom, 1); - - XMapWindow(display_, window_);*/ - - updateRegion_ = XCreateRegion(); - - logTest("Updater::init", "updateRegion_[%p]", updateRegion_); - return 1; -} - -void Updater::addRegion(Region region) -{ - // - // FIXME: Is this too paranoid ? - // - - if (updateRegion_ == NULL) - { - logError("Updater::addRegion", ESET(EINVAL)); - - return; - } - - XUnionRegion(region, updateRegion_, updateRegion_); -} - -void Updater::update() -{ - logTrace("Updater::update"); - - if (updateRegion_ == NULL) - { - logError("Updater::update", ESET(EINVAL)); - - return; - } - - logTest("Updater::update", "Number of rectangles [%ld].", updateRegion_ -> numRects); - -/* for (; updateRegion_ -> numRects > 0; updateRegion_ -> numRects--) - { - int n = updateRegion_ -> numRects - 1; - - int x = updateRegion_ -> rects[n].x1; - int y = updateRegion_ -> rects[n].y1; - unsigned int width = updateRegion_ -> rects[n].x2 - updateRegion_ -> rects[n].x1; - unsigned int height = updateRegion_ -> rects[n].y2 - updateRegion_ -> rects[n].y1; - - logDebug("Updater::update", "Sending rectangle: [%d, %d, %d, %d].", x, y, width, height); - - // - // We need to update the extents. - // - - int bitmap_pad; - - if (depth_ == 32 || depth_ == 24) - { - bitmap_pad = 32; - } - else if (depth_ == 16) - { - if ((width & 1) == 0) - { - bitmap_pad = 32; - } - else - { - bitmap_pad = 16; - } - } - else if ((width & 3) == 0) - { - bitmap_pad = 32; - } - else if ((width & 1) == 0) - { - bitmap_pad = 16; - } - else - { - bitmap_pad = 8; - }*/ - -/* image_ -> bitmap_pad = bitmap_pad;*/ - - /* NXShadowCorrectColor(x, y, width, height);*/ - -/* XPutImage(display_, pixmap_, DefaultGC(display_, DefaultScreen(display_)), - image_, x, y, x, y, width, height); - - XClearArea(display_, window_, x, y, width, height, 0); - }*/ - - // - // Should we reduces the box vector ? - // - // BOX *box = Xrealloc(updateRegion_ -> rects, - // updateRegion_ -> numRects == 0 ? sizeof(BOX) : - // updateRegion_ -> numRects * sizeof(BOX)); - // - // if (box) - // { - // updateRegion_ -> rects = box; - // updateRegion_ -> size = 1; - // } - // - - if (updateRegion_ -> numRects == 0) - { - updateRegion_ -> extents.x1 = 0; - updateRegion_ -> extents.y1 = 0; - updateRegion_ -> extents.x2 = 0; - updateRegion_ -> extents.y2 = 0; - } - else - { - // - // FIXME: We have to update the region extents. - // - - logTest("Updater::update", "Region extents has not been updated."); - } -} - -void Updater::handleInput() -{ - logTrace("Updater::handleInput"); - - XEvent *event = new XEvent; - - if (event == NULL) - { - logError("Updater::handleInput", ESET(ENOMEM)); - - return; - } - - while (XCheckIfEvent(display_, event, anyEventPredicate, NULL)) - { - switch (event -> type) - { - /* case ClientMessage: - { - Atom wmProtocols = XInternAtom(display_, "WM_PROTOCOLS", 0); - Atom wmDeleteWindow = XInternAtom(display_, "WM_DELETE_WINDOW", 0); - - if (event -> xclient.message_type == wmProtocols && - (Atom)event -> xclient.data.l[0] == wmDeleteWindow) - { - logTest("Updater::handleInput", "Got client message of type WM_PROTOCOLS and value WM_DELETE_WINDOW," - " throwing exception UpdaterClosing."); - - delete event; - - throw UpdaterClosing(); - } - else - { - logTest("Updater::handleInput", "Unexpected client message type [%ld] format [%d] first value [%ld]", - event -> xclient.message_type, event -> xclient.format, event -> xclient.data.l[0]); - } - - break; - }*/ - case KeyPress: - case KeyRelease: - case ButtonPress: - case ButtonRelease: - case MotionNotify: - { - input_ -> pushEvent(display_, event); - - event = new XEvent; - - if (event == NULL) - { - logError("Updater::handleInput", ESET(ENOMEM)); - - return; - } - - break; - } - default: - { - logTest("Updater::handleInput", "Handling unexpected event [%d].", event -> type); - - break; - } - } - } - - delete event; -} - -void Updater::newRegion() -{ - if (updateRegion_ != NULL) - { - XDestroyRegion(updateRegion_); - } - - updateRegion_ = XCreateRegion(); - - logTest("Updater::newRegion", "updateRegion_ [%p].", updateRegion_); -} -// -// Private functions. -// diff --git a/nxcompshad/Updater.h b/nxcompshad/Updater.h deleted file mode 100644 index 10d75c0d6..000000000 --- a/nxcompshad/Updater.h +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef Updater_H -#define Updater_H - -#include - -#include "Regions.h" -#include "Input.h" - -class UpdaterClosing {}; - -class Updater -{ - public: - - Updater(char *displayName, Display *display); - - ~Updater(); - - int init(int, int, char *, Input*); - - void addRegion(Region r); - - void update(); - - void handleInput(); - - XImage *getImage(); - - Region getUpdateRegion(); - - void newRegion(); - - private: - - Input *input_; - - static inline Bool anyEventPredicate(Display*, XEvent*, XPointer); - - void handleKeyboardEvent(XEvent &event); - - char *displayName_; - - char *buffer_; - - bool closeDisplay_; - - Display *display_; - - int depth_; - - int width_; - int height_; - - int bpl_; - - Window window_; - XImage *image_; - - Pixmap pixmap_; - - Region updateRegion_; - -}; - -Bool Updater::anyEventPredicate(Display*, XEvent*, XPointer) -{ - return true; -} - -inline XImage* Updater::getImage() -{ - return image_; -} -inline Region Updater::getUpdateRegion() -{ - return updateRegion_; -} -#endif /* Updater_H */ diff --git a/nxcompshad/Win.cpp b/nxcompshad/Win.cpp deleted file mode 100644 index b3a06f415..000000000 --- a/nxcompshad/Win.cpp +++ /dev/null @@ -1,1145 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#if defined(__CYGWIN32__) || defined(WIN32) - -#include - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include "Poller.h" -#include "Logger.h" - -Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display) -{ - logTrace("Poller::Poller"); - - screenDC_ = NULL; - screenBmp_ = NULL; - memoryDC_ = NULL; - pDIBbits_ = NULL; - DIBBuffer_ = NULL; - pKey_ = NULL; - pMouse_ = NULL; - path_ = NULL; - keymapName_ = input -> getKeymap(); - keymap_ = NULL; - toggleButtonState_ = 0; - serverModifierState_ = 0; - display_ = display; - depth_ = DefaultDepth(display_, DefaultScreen(display_)); - oldCursor_ = 0; - xCursor_ = 0; -} - -Poller::~Poller() -{ - logTrace("Poller::~Poller"); - - if (screenDC_) - { - BOOL result = ReleaseDC(NULL, screenDC_); - - logTest("Poller::~Poller", "ReleaseDC returned [%d].", result); - - screenDC_ = NULL; - } - - if (memoryDC_) - { - BOOL result = DeleteDC(memoryDC_); - - logTest("Poller::~Poller", "DeleteDC returned [%d].", result); - - memoryDC_ = NULL; - } - - if (screenBmp_) - { - BOOL result = DeleteObject(screenBmp_); - - logTest("Poller::~Poller", "DeleteObject returned [%d].", result); - - screenBmp_ = NULL; - } - - if (DIBBuffer_) - { - logDebug("Poller::~Poller", "Delete DIBBuffer_ [%p].", DIBBuffer_); - - delete [] DIBBuffer_; - } - - if (pKey_) - { - logDebug("Poller::~Poller", " pKey_[%p].", pKey_); - - delete [] pKey_; - } - - if (pMouse_) - { - logDebug("Poller::~Poller", " pMouse_[%p].", pMouse_); - - delete [] pMouse_; - } - - if (keymap_) - { - logDebug("Poller::~Poller", " keymap_[%p].", keymap_); - - delete [] keymap_; - } -} - -int Poller::init() -{ - logTrace("Poller::init"); - - int maxLengthArrayINPUT = 6; - - platformOS(); - - pKey_ = new INPUT [maxLengthArrayINPUT]; - - if (pKey_ == NULL) - { - logError("Poller::init", ESET(ENOMEM)); - - return -1; - } - - for (int i = 0; i < maxLengthArrayINPUT; i++) - { - pKey_[i].type = INPUT_KEYBOARD; - pKey_[i].ki.wVk = (WORD) 0; - pKey_[i].ki.time = (DWORD) 0; - pKey_[i].ki.dwExtraInfo = (DWORD) 0; - } - - pMouse_ = new INPUT; - - if (pMouse_ == NULL) - { - logError("Poller::init", ESET(ENOMEM)); - - return -1; - } - - pMouse_ -> type = INPUT_MOUSE; - - pMouse_ -> mi.dx = 0; - pMouse_ -> mi.dy = 0; - pMouse_ -> mi.mouseData = (DWORD) 0; - pMouse_ -> mi.time = 0; - pMouse_ -> mi.dwExtraInfo = (ULONG_PTR) NULL; - - screenDC_ = GetDC(NULL); - - if (screenDC_ == NULL) - { - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - switch(depth_) - { - case 8: - { - depth_ = 16; - break; - } - case 16: - { - depth_ = 16; - break; - } - case 24: - { - depth_ = 32; - break; - } - default: - { - logError("Poller::init", ESET(EINVAL)); - - return -1; - } - } - - width_ = GetDeviceCaps(screenDC_, HORZRES); - height_ = GetDeviceCaps(screenDC_, VERTRES); - - bpl_ = width_ * (depth_ >> 3); - bpp_ = (depth_ >> 3); - - logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].", - width_, height_, depth_, bpl_, bpp_); - - logTest("Poller::init", "Got device context at [%p] screen size is (%d,%d).", - screenDC_, width_, height_); - - memoryDC_ = CreateCompatibleDC(screenDC_); - - if (memoryDC_ == NULL) - { - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - // - // Delete the old bitmap for the memory device. - // - - HBITMAP bitmap = (HBITMAP) GetCurrentObject(memoryDC_, OBJ_BITMAP); - - if (bitmap && DeleteObject(bitmap) == 0) - { - logError("Poller::init", ESET(ENOMSG)); - } - - // - // Bitmap header describing the bitmap we want to get from GetDIBits. - // - - bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi_.bmiHeader.biWidth = width_; - bmi_.bmiHeader.biHeight = -height_; - bmi_.bmiHeader.biPlanes = 1; - bmi_.bmiHeader.biBitCount = depth_; - bmi_.bmiHeader.biCompression = BI_RGB; - bmi_.bmiHeader.biSizeImage = 0; - bmi_.bmiHeader.biXPelsPerMeter = 0; - bmi_.bmiHeader.biYPelsPerMeter = 0; - bmi_.bmiHeader.biClrUsed = 0; - bmi_.bmiHeader.biClrImportant = 0; - - screenBmp_ = CreateDIBSection(memoryDC_, &bmi_, DIB_RGB_COLORS, &pDIBbits_, NULL, 0); - ReleaseDC(NULL,memoryDC_); - - if (screenBmp_ == NULL) - { - logTest ("Poller::init", "This video device is not supporting DIB section"); - - pDIBbits_ = NULL; - - screenBmp_ = CreateCompatibleBitmap(screenDC_, width_, height_); - - if (screenBmp_ == NULL) - { - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - if (SelectObject(memoryDC_, screenBmp_) == NULL) - { - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - } - else - { - logTest ("Poller::init", "Enabled the DIB section"); - - if (SelectObject(memoryDC_, screenBmp_) == NULL) - { - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - } - - // - // Check if the screen device raster capabilities - // support the bitmap transfer. - // - - if ((GetDeviceCaps(screenDC_, RASTERCAPS) & RC_BITBLT) == 0) - { - logTest("Poller::init", "This video device is not supporting the bitmap transfer."); - - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - // - // Check if the memory device raster capabilities - // support the GetDIBits and SetDIBits functions. - // - - if ((GetDeviceCaps(memoryDC_, RASTERCAPS) & RC_DI_BITMAP) == 0) - { - logTest("Poller::init", "This memory device is not supporting the GetDIBits and SetDIBits " - "function."); - - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - if (GetDeviceCaps(screenDC_, PLANES) != 1) - { - logTest("Poller::init", "This video device has more than 1 color plane."); - - logError("Poller::init", ESET(ENOMSG)); - - return -1; - } - - return CorePoller::init(); -} - -// -// FIXME: Remove me. -// - -void ErrorExit(LPTSTR lpszFunction) -{ - LPVOID lpMsgBuf; - DWORD dw = GetLastError(); - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - - logTest(lpszFunction, " Failed with error [%ld]: %s", dw, (char*)lpMsgBuf); - - LocalFree(lpMsgBuf); - ExitProcess(dw); -} - -// -// FIXME: End. -// - -char *Poller::getRect(XRectangle r) -{ - logTrace("Poller::getRect"); - - logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].", - r.x, r.y, r.width, r.height); - - // - // The CAPTUREBLT operation could be a very - // cpu-consuming task. We should make some - // test to see how much it is expensive. - // Anyway we get tooltip windows and any - // other special effect not included with - // only the SRCCOPY operation. - // - - if (BitBlt(memoryDC_, r.x, r.y, r.width, r.height, - screenDC_, r.x, r.y, SRCCOPY | CAPTUREBLT) == 0) - { - logError("Poller::getRect", ESET(ENOMSG)); - - logTest("Poller::getRect", "Failed to perform a bit-block transfer."); - logTest("Poller::getRect", "bit-block error=%lu", GetLastError()); - - return NULL; - } - - // bmi_.bmiHeader.biWidth = r.width; - // bmi_.bmiHeader.biHeight = -r.height; - - if (pDIBbits_ == NULL) - { - static long nPixel = 0; - - if (nPixel < r.width * r.height) - { - - if (DIBBuffer_) - { - delete [] DIBBuffer_; - } - - nPixel = r.width * r.height; - - DIBBuffer_ = new char [nPixel * bpp_]; - - if (DIBBuffer_ == NULL) - { - logError("Poller::getRect", ESET(ENOMEM)); - - nPixel = 0; - - return NULL; - } - } - - if (GetDIBits(memoryDC_, screenBmp_, height_ - r.height - r.y, r.height, - DIBBuffer_, &bmi_, DIB_RGB_COLORS) == 0) - { - logError("Poller::getRect", ESET(ENOMSG)); - - logTest("Poller::getRect", "Failed to retrieve the screen bitmap."); - - return NULL; - } - - return DIBBuffer_; - } - else - { - return (char *) pDIBbits_ + r.y * bpl_ + r.x * bpp_; - } -} - -void Poller::handleKeyboardEvent(Display *display, XEvent *event) -{ - KeySym keysym; - char *keyname = new char [31]; - keyTranslation tr = {0, 0}; - unsigned char scancode = 0; - int lengthArrayINPUT = 0; - - if (XLookupString((XKeyEvent *) event, keyname, 30, &keysym, NULL) > 0) - { - logTest("Poller::handleKeyboardEvent", "keyname %s, keysym [%x]", keyname, (unsigned int)keysym); - } - - if (specialKeys(keysym, event -> xkey.state, event -> type) == 1) - { - delete[] keyname; - return; - } - - tr = xkeymapTranslateKey(keysym, event -> xkey.keycode, event -> xkey.state); - scancode = tr.scancode; - - logTest("Poller::handleKeyboardEvent", "keyname [%s] scancode [0x%x], keycode[0x%x], keysym [%x]", keyname, - tr.scancode, event ->xkey.keycode, (unsigned int)keysym); - - if (scancode == 0) - { - delete[] keyname; - return; - } - - if (event -> type == KeyPress) - { - int test1 = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); - int test2 = MapVirtualKey(0x24, MAPVK_VSC_TO_VK_EX); - - if (test1 == test2) - { - simulateCtrlAltDel(); - } - - if (isModifier(scancode) == 0) - { - savedServerModifierState_ = serverModifierState_; - } - - ensureServerModifiers(tr, &lengthArrayINPUT); - if (sendInput(scancode, 1, &lengthArrayINPUT) == 0) - { - logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); - } - restoreServerModifiers(scancode); - } - else if (event -> type == KeyRelease) - { - if (sendInput(scancode, 0, &lengthArrayINPUT) == 0) - { - logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); - } - } - - updateModifierState(scancode, (event -> type == KeyPress)); - - delete[] keyname; -} - -void Poller::handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) -{ -/* -FIXME -*/ -} - -void Poller::handleMouseEvent(Display *display, XEvent *event) -{ - DWORD flg = 0; - DWORD whl = 0; - - if (event -> type == ButtonPress) - { - logTest("Poller::handleMouseEvent", "ButtonPress.\n"); - switch (event -> xbutton.button) - { - case Button1: - { - flg = MOUSEEVENTF_LEFTDOWN; - break; - } - case Button2: - { - flg = MOUSEEVENTF_MIDDLEDOWN; - break; - } - case Button3: - { - flg = MOUSEEVENTF_RIGHTDOWN; - break; - } - case Button4: - { - flg = MOUSEEVENTF_WHEEL; - whl = WHEEL_DELTA; - pMouse_ -> mi.mouseData = whl; - break; - } - case Button5: - { - flg = MOUSEEVENTF_WHEEL; - whl = (DWORD) (-WHEEL_DELTA); - pMouse_ -> mi.mouseData = whl; - break; - } - } - } - else if (event -> type == ButtonRelease) - { - switch (event -> xbutton.button) - { - case Button1: - { - flg = MOUSEEVENTF_LEFTUP; - break; - } - case Button2: - { - flg = MOUSEEVENTF_MIDDLEUP; - break; - } - case Button3: - { - flg = MOUSEEVENTF_RIGHTUP; - break; - } - case Button4: - { - flg = MOUSEEVENTF_WHEEL; - whl = 0; - pMouse_ -> mi.mouseData = whl; - break; - } - case Button5: - { - flg = MOUSEEVENTF_WHEEL; - whl = 0; - pMouse_ -> mi.mouseData = whl; - break; - } - } - } - else if (event -> type == MotionNotify) - { - logTest("Poller::handleMouseEvent", "SetCursor - MotionNotify"); - - SetCursorPos(event -> xmotion.x, event -> xmotion.y); - } - - if (flg > 0) - { - // logTest("Poller::handleMouseEvent", "SetCursor - flg > 0"); - // - // FIXME: move the cursor to the pace the event occurred - // - - SetCursorPos(event -> xbutton.x, event -> xbutton.y); - - // - // FIXME: Remove me: send the click/release event - // mouse_event(flg, 0, 0, whl, (ULONG_PTR)NULL); - // - - pMouse_ -> mi.dwFlags = flg; - - if (SendInput(1, pMouse_, sizeof(INPUT)) == 0) - { - logTest("Poller::handleMouseEvent", "Failed SendInput"); - } - } -} - -int Poller::updateCursor(Window wnd, Visual* vis) -{ - BYTE *mBits, *andBits, *xorBits; - - logTrace("Poller::Cursor"); - - // - // Retrieve mouse cursor handle. - // - - CURSORINFO cursorInfo; - cursorInfo.cbSize = sizeof(CURSORINFO); - - if (GetCursorInfo(&cursorInfo) == 0) - { - logTest("Poller::Cursor", "GetCursorInfo() failed [%u].\n", (unsigned int)GetLastError()); - LocalFree(&cursorInfo); - return -1; - } - - HCURSOR hCursor = cursorInfo.hCursor; - - if (hCursor == 0) - { - logTest("Poller::Cursor","Cursor Handle is NULL. Error[%u].\n", (unsigned int)GetLastError()); - return 1; - } - - if (hCursor == oldCursor_) - { - LocalFree(&cursorInfo); - return 1; - } - else - { - oldCursor_ = hCursor; - } - - // - // Get cursor info. - // - - // logTest("Poller::Cursor","hCursor [%xH] GetCursor [%xH].\n", hCursor, GetCursor()); - - ICONINFO iconInfo; - if (GetIconInfo(hCursor, &iconInfo) == 0) - { - logTest("Poller::Cursor","GetIconInfo() failed. Error[%d].", (unsigned int)GetLastError()); - LocalFree(&iconInfo); - // return -1; - } - - BOOL isColorCursor = FALSE; - if (iconInfo.hbmColor != NULL) - { - isColorCursor = TRUE; - } - - if (iconInfo.hbmMask == NULL) - { - logTest("Poller::Cursor","Cursor bitmap handle is NULL.\n"); - return -1; - } - - // - // Check bitmap info for the cursor - // - - BITMAP bmMask; - if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), (LPVOID)&bmMask)) - { - logTest("Poller::Cursor","GetObject() for bitmap failed.\n"); - DeleteObject(iconInfo.hbmMask); - LocalFree(&bmMask); - return -1; - } - - if (bmMask.bmPlanes != 1 || bmMask.bmBitsPixel != 1) - { - logTest("Poller::Cursor","Incorrect data in cursor bitmap.\n"); - LocalFree(&bmMask); - DeleteObject(iconInfo.hbmMask); - return -1; - } - - // Get monochrome bitmap data for cursor - // NOTE: they say we should use GetDIBits() instead of GetBitmapBits(). - mBits = new BYTE[bmMask.bmWidthBytes * bmMask.bmHeight]; - - if (mBits == NULL)//Data bitmap - { - DeleteObject(iconInfo.hbmMask); - DestroyCursor(cursorInfo.hCursor); - LocalFree(&iconInfo); - LocalFree(&bmMask); - delete[] mBits; - return -1; - } - - BOOL success = GetBitmapBits(iconInfo.hbmMask, bmMask.bmWidthBytes * bmMask.bmHeight, mBits); - - if (!success) - { - logTest("Poller::Cursor","GetBitmapBits() failed.\n"); - delete[] mBits; - return -1; - } - - andBits = mBits; - - long width = bmMask.bmWidth; - long height = (isColorCursor) ? bmMask.bmHeight : bmMask.bmHeight/2; - - // - // The bitmask is formatted so that the upper half is - // the icon AND bitmask and the lower half is the icon XOR bitmask. - // - - if (!isColorCursor) - { - xorBits = andBits + bmMask.bmWidthBytes * height; - -/* logTest("Poller::Cursor","no color widthB[%ld] width[%ld] height[%ld] totByte[%ld] mbits[%ld].\n", - bmMask.bmWidthBytes,width,height,success,bmMask.bmHeight * bmMask.bmWidthBytes);*/ - - if (xCursor_ > 0) - { - XFreeCursor(display_, xCursor_); - } - - xCursor_ = createCursor(wnd, vis, (unsigned int)iconInfo.xHotspot, (unsigned int)iconInfo.yHotspot, - width, height, (unsigned char *)xorBits, (unsigned char *)andBits); - - XDefineCursor(display_, wnd, xCursor_); - } - - delete []mBits; - DeleteObject(iconInfo.hbmMask); - LocalFree(&bmMask); - DestroyCursor(cursorInfo.hCursor); - LocalFree(&iconInfo); - - return success; -} - -unsigned char Poller::specialKeys(unsigned int keysym, unsigned int state, int pressed) -{ - return 0; -} - -void Poller::ensureServerModifiers(keyTranslation tr, int *lengthArrayINPUT) -{ - return; -} - -void Poller::restoreServerModifiers(UINT scancode) -{ - keyTranslation dummy; - int lengthArrayINPUT = 0; - - if (isModifier(scancode) == 1) - { - return; - } - - dummy.scancode = 0; - dummy.modifiers = savedServerModifierState_; - ensureServerModifiers(dummy, &lengthArrayINPUT); - if (sendInput(0, 0, &lengthArrayINPUT) == 0) - { - logTest("Poller::restoreServerModifiers", "lengthArrayINPUT [%d]", lengthArrayINPUT); - } -} - -int Poller::updateShadowFrameBuffer(void) -{ - return 1; -} - -void Poller::addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname) -{ - return; -} - -FILE *Poller::xkeymapOpen(char *filename) -{ - return NULL; -} - -int Poller::xkeymapRead(char *mapname) -{ - return 1; -} - -void Poller::xkeymapInit(char *keyMapName) -{ - return; -} - -keyTranslation Poller::xkeymapTranslateKey(unsigned int keysym, unsigned int keycode, - unsigned int state) -{ - keyTranslation tr = { 0, 0 }; - - return tr; -} - -unsigned char Poller::getKeyState(unsigned int state, unsigned int keysym) -{ - return 0; -} - -char *Poller::getKsname(unsigned int keysym) -{ - char *ksname = NULL; - - return ksname; -} - -// -// Routine used to fool Winlogon into thinking CtrlAltDel was pressed -// -char Poller::simulateCtrlAltDel(void) -{ - HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); - - // - // Switch into the Winlogon desktop. - // - if (selectDesktopByName("Winlogon") == 0) - { - logTest("SimulateCtrlAltDelThreadFn","Failed to select logon desktop."); - return 0; - } - - logTest("SimulateCtrlAltDelThreadFn","Generating ctrl-alt-del."); - - // - // Winlogon uses hotkeys to trap Ctrl-Alt-Del. - // - PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); - - // - // Switch back to our original desktop. - // - if (oldDesktop != NULL) - { - selectDesktop(oldDesktop); - } - - return 1; -} - -// Switches the current thread into a different desktop by desktop handle -// This call takes care of all the evil memory management involved -char Poller::selectDesktop(HDESK newDesktop) -{ - // - // Only on NT. - // - if (isWinNT()) - { - HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); - - DWORD dummy; - char newName[256]; - - if (GetUserObjectInformation(newDesktop, UOI_NAME, &newName, 256, &dummy) == 0) - { - logDebug("Poller::selectDesktop","GetUserObjectInformation() failed. Error[%lu].", GetLastError()); - return 0; - } - - logTest("Poller::selectDesktop","New Desktop to [%s] (%x) from (%x).", - newName, (unsigned int)newDesktop, (unsigned int)oldDesktop); - - // - // Switch the desktop. - // - if(SetThreadDesktop(newDesktop) == 0) - { - logDebug("Poller::SelectDesktop","Unable to SetThreadDesktop(), Error=%lu.", GetLastError()); - return 0; - } - - // - // Switched successfully - destroy the old desktop. - // - if (CloseDesktop(oldDesktop) == 0) - { - logDebug("Poller::selectHdesk","Failed to close old desktop (%x), Error=%lu.", - (unsigned int)oldDesktop, GetLastError()); - return 0; - } - } - - return 1; -} - -// -// Switches the current thread into a different desktop, by name -// Calling with a valid desktop name will place the thread in that desktop. -// Calling with a NULL name will place the thread in the current input desktop. -// - -char Poller::selectDesktopByName(char *name) -{ - // - // Only on NT. - // - if (isWinNT()) - { - HDESK desktop; - - if (name != NULL) - { - // - // Attempt to open the named desktop. - // - desktop = OpenDesktop(name, 0, FALSE, - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | - DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | - DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); - } - else - { - // - // Open the input desktop. - // - desktop = OpenInputDesktop(0, FALSE, - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | - DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | - DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); - } - - if (desktop == NULL) - { - logDebug("Poller::selectDesktopByName","Unable to open desktop, Error=%lu.", GetLastError()); - return 0; - } - - // - // Switch to the new desktop - // - if (selectDesktop(desktop) == 0) - { - // - // Failed to enter the new desktop, so free it! - // - logDebug("Poller::selectDesktopByName","Failed to select desktop."); - - if (CloseDesktop(desktop) == 0) - { - logDebug("Poller::selectDesktopByName","Failed to close desktop, Error=%lu.", GetLastError()); - return 0; - } - } - - return 1; - } - - return (name == NULL); -} - -void Poller::platformOS() -{ - OSVERSIONINFO osversioninfo; - osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo); - - // - // Get the current OS version. - // - if (GetVersionEx(&osversioninfo) == 0) - { - platformID_ = 0; - } - platformID_ = osversioninfo.dwPlatformId; - -// -// versionMajor = osversioninfo.dwMajorVersion; -// versionMinor = osversioninfo.dwMinorVersion; -// -} - -char Poller::checkDesktop() -{ - // - // Only on NT. - // - if (isWinNT()) - { - // - // Get the input and thread desktops. - // - HDESK desktop = GetThreadDesktop(GetCurrentThreadId()); - HDESK inputDesktop = OpenInputDesktop(0, FALSE, - DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | - DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | - DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | - DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); - - if (inputDesktop == NULL) - { - return 0; - } - - DWORD dummy; - char desktopName[256]; - char inputName[256]; - - if (GetUserObjectInformation(desktop, UOI_NAME, &desktopName, 256, &dummy) == 0) - { - if (CloseDesktop(inputDesktop) == 0) - { - logDebug("Poller::checkDesktop", "Failed to close desktop, Error[%d].", (unsigned int)GetLastError()); - return 0; - } - } - - if (GetUserObjectInformation(inputDesktop, UOI_NAME, &inputName, 256, &dummy) == 0) - { - if (CloseDesktop(inputDesktop) == 0) - { - logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); - return 0; - } - } - - if (strcmp(desktopName, inputName) != 0) - { - // - // Switch to new desktop. - // - selectDesktop(inputDesktop); - } - - if (CloseDesktop(desktop) == 0) - { - logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); - return 0; - } - - if (CloseDesktop(inputDesktop) == 0) - { - logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); - return 0; - } - } - - return 1; -} - -unsigned char Poller::isModifier(UINT scancode) -{ - return 0; -} - -void Poller::updateModifierState(UINT scancode, unsigned char pressed) -{ - return; -} - -Cursor Poller::createCursor(Window wnd, Visual *vis,unsigned int x, unsigned int y, - int width, int height, unsigned char *xormask, unsigned char *andmask) -{ - Pixmap maskglyph, cursorglyph; - XColor bg, fg; - Cursor xcursor; - unsigned char *cursor; - unsigned char *mask, *pmask, *pcursor, tmp; - int scanline, offset; - - scanline = (width + 7) / 8; - offset = scanline * height; - - pmask = andmask; - pcursor = xormask; - for (int i = 0; i < offset; i++) - { - // - // The pixel is black if both the bit of andmask and xormask is one. - // - - tmp = *pcursor & *pmask; - *pcursor ^= tmp; - *pmask ^= tmp; - - *pmask = ~(*pmask); - - pmask++; - pcursor++; - } - - cursor = new unsigned char[offset]; - memcpy(cursor, xormask, offset); - - mask = new unsigned char[offset]; - memcpy(mask, andmask, offset); - - fg.red = fg.blue = fg.green = 0xffff; - bg.red = bg.blue = bg.green = 0x0000; - fg.flags = bg.flags = DoRed | DoBlue | DoGreen; - - cursorglyph = createGlyph(wnd, vis, width, height, cursor); - maskglyph = createGlyph(wnd, vis, width, height, mask); - - xcursor = XCreatePixmapCursor(display_, cursorglyph, maskglyph, &fg, &bg, x, y); - - XFreePixmap(display_, maskglyph); - XFreePixmap(display_, cursorglyph); - delete[]mask; - delete[]cursor; - - return xcursor; -} - -Pixmap Poller::createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data) -{ - XImage *image; - Pixmap bitmap; - int scanline; - GC glyphGC; - - scanline = (width + 7) / 8; - - bitmap = XCreatePixmap(display_, wnd, width, height, 1); - glyphGC = XCreateGC(display_, bitmap, 0, NULL); - - image = XCreateImage(display_, visual, 1, ZPixmap, 0, (char *)data, width, height, 8, scanline); - image->byte_order = 1; // MSBFirst -- LSBFirst = 0 - image->bitmap_bit_order = 1; - XInitImage(image); - -/* logTest("Poller::createGlyph","XPutImage on pixmap %d,%d,%d,%d.\n", - 0, 0, width, height);*/ - XPutImage(display_, bitmap, glyphGC, image, 0, 0, 0, 0, width, height); - XFree(image); - - return bitmap; -} -#endif /* defined(__CYGWIN32__) || defined(WIN32) */ diff --git a/nxcompshad/Win.h b/nxcompshad/Win.h deleted file mode 100644 index 615f9a5f5..000000000 --- a/nxcompshad/Win.h +++ /dev/null @@ -1,232 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifdef __CYGWIN32__ - -#ifndef Win32Poller_H -#define Win32Poller_H - -//#include - -#include -#include -#include -#include - -#define CAPTUREBLT 0x40000000 - -#define KEYEVENTF_SCANCODE 0x00000008 -#define MAPVK_VSC_TO_VK_EX 3 -// -// The CAPTUREBLT is a raster operation used -// in bit blit transfer. -// -// Using this operation includes any windows -// that are layered on top of your window in -// the resulting image. By default, the image -// only contains your window. -// - -#include "Core.h" - -typedef struct _keyTranslation -{ - unsigned char scancode; - unsigned short modifiers; - -}keyTranslation; - -class Poller : public CorePoller -{ - public: - - Display *display_; - keyTranslation *keymap_; - unsigned char keymapLoaded_; - int minKeycode_; - - Poller(Input *, Display *display, int = 16); - - ~Poller(); - - int init(); - - int updateCursor(Window, Visual*); - - private: - - - int Poller::updateShadowFrameBuffer(void); - void handleKeyboardEvent(Display *, XEvent *); - void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress); - void addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname); - int xkeymapRead(char *mapname); - FILE *xkeymapOpen(char *filename); - void xkeymapInit(char *keyMapName); - keyTranslation xkeymapTranslateKey(unsigned int keysym, unsigned int keycode, unsigned int state); - unsigned char getKeyState(unsigned int state, unsigned int keysym); - char *getKsname(unsigned int keysym); - unsigned char specialKeys(unsigned int keysym, unsigned int state, int pressed); - - unsigned char toggleSwitch(unsigned char ToggleStateClient, unsigned char ToggleStateServer, UINT scancode, - int *lengthArrayINPUT); - - void updateModifierState(UINT, unsigned char); - - unsigned char toggleServerState(UINT scancode); - unsigned char keyState(UINT scancode, UINT mapType); - unsigned char keyStateAsync(UINT scancode); - - void handleMouseEvent(Display *, XEvent *); - - Cursor createCursor(Window wnd, Visual *vis, unsigned int x, unsigned int y, int width, - int height, unsigned char *xormask, unsigned char *andmask); - - Pixmap createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data); - - char isWinNT(); - char selectDesktop(HDESK new_desktop); - char selectDesktopByName(char *name); - void platformOS(); - char simulateCtrlAltDel(void); - DWORD platformID_; - - INPUT *pKey_, *pMouse_; - - char *keymapName_; - char *path_; - - unsigned char toggleButtonState_; - unsigned short serverModifierState_; - unsigned short savedServerModifierState_; - - void ensureServerModifiers(keyTranslation tr, int *lenghtArrayINPUT); - void restoreServerModifiers(UINT scancode); - unsigned char isModifier(UINT scancode); - - char sendInput(unsigned char scancode, unsigned char pressed, int *lengthArrayINPUT); - - char *getRect(XRectangle); - char checkDesktop(); - - char *DIBBuffer_; - - HCURSOR oldCursor_; - - VOID *pDIBbits_; - HDC screenDC_; - HDC memoryDC_; - BITMAPINFO bmi_; - HBITMAP screenBmp_; - - Cursor xCursor_; - -}; - -#undef TEST - -inline unsigned char Poller::toggleSwitch(unsigned char ToggleStateClient, unsigned char ToggleStateServer, - UINT scancode, int *lengthArrayINPUT) -{ - return 1; -} - -inline unsigned char Poller::toggleServerState(UINT scancode) -{ - return (GetKeyState(MapVirtualKeyEx(scancode, 3, GetKeyboardLayout((DWORD)NULL))) & 0x1); -} - -inline unsigned char Poller::keyStateAsync(UINT vKeycode) -{ - return GetAsyncKeyState(vKeycode); -} - -inline unsigned char Poller::keyState(UINT code, UINT mapType) -{ - if (mapType == 0) - { - // - // Virtual Keycode - // - return ((GetKeyState(code) & 0x80) == 0x80); - } - else - { - // - // scancode - // - return ((GetKeyState(MapVirtualKeyEx(code, 3, GetKeyboardLayout((DWORD)NULL))) & 0x80) == 0x80); - } -} - -inline char Poller::isWinNT() -{ - return (platformID_ == VER_PLATFORM_WIN32_NT); -} - -inline char Poller::sendInput(unsigned char scancode, unsigned char pressed, int *lengthArrayINPUT) -{ - DWORD keyEvent = 0; - DWORD extended = 0; - - if (scancode > 0) - { - if (pressed == 0) - { - keyEvent = KEYEVENTF_KEYUP; - } - - if (scancode & 0x80) - { - scancode &= ~0x80; - extended = KEYEVENTF_EXTENDEDKEY; - } - - pKey_[*lengthArrayINPUT].ki.wScan = (WORD) scancode; - pKey_[*lengthArrayINPUT].ki.dwFlags = (DWORD) (keyEvent | KEYEVENTF_SCANCODE | extended); - (*lengthArrayINPUT)++; - } - - - if (*lengthArrayINPUT > 0) { - // FIXME: Remove me. - logTest("Poller::sendInput", "length Input [%d] event: %s", *lengthArrayINPUT, - pressed == 1 ? "KeyPress": "KeyRelease"); - - if (SendInput(*lengthArrayINPUT, pKey_, sizeof(INPUT)) == 0) - { - logTest("Poller::sendInput", "Failed SendInput, event: %s", pressed == 1 ? "KeyPress": "KeyRelease"); - *lengthArrayINPUT = 0; - return 0; - } - - *lengthArrayINPUT = 0; - } - - return 1; -} -#endif /* Win32Poller_H */ - -#endif /* __CYGWIN32__ */ diff --git a/nxcompshad/X11.cpp b/nxcompshad/X11.cpp deleted file mode 100644 index d1af82281..000000000 --- a/nxcompshad/X11.cpp +++ /dev/null @@ -1,1594 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#if !defined(__CYGWIN32__) && !defined(WIN32) - -#define PANIC -#define WARNING -#undef TEST -#undef DEBUG - -#include -#include -#include -#include "X11/include/XTest_nxcompshad.h" -#include -#include -#include - -#include "Poller.h" -#include "Logger.h" -#include "Shadow.h" - -#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) - -#undef TRANSLATE_KEYCODES -#define TRANSLATE_ALWAYS - -typedef struct { - KeySym *map; - KeyCode minKeyCode, - maxKeyCode; - int mapWidth; -} KeySymsRec, *KeySymsPtr; - -extern KeySymsPtr NXShadowKeymap; - -typedef struct _KeyPressed -{ - KeyCode keyRcvd; - KeyCode keySent; - struct _KeyPressed *next; -} KeyPressedRec; - -static KeyPressedRec *shadowKeyPressedPtr = NULL; - -static KeySym *shadowKeysyms = NULL; -static KeySym *masterKeysyms = NULL; - -static KeySym *shadowKeymap = NULL; - -static int shadowMinKey, shadowMaxKey, shadowMapWidth; -static int masterMinKey, masterMaxKey, masterMapWidth; - -static int leftShiftOn = 0; -static int rightShiftOn = 0; -static int modeSwitchOn = 0; -static int level3ShiftOn = 0; -static int altROn = 0; - -static int sentFakeLShiftPress = 0; -static int sentFakeLShiftRelease = 0; -static int sentFakeRShiftRelease = 0; -static int sentFakeModeSwitchPress = 0; -static int sentFakeModeSwitchRelease = 0; -static int sentFakeLevel3ShiftPress = 0; -static int sentFakeLevel3ShiftRelease = 0; -static int sentFakeAltRRelease = 0; - -static int shmInitTrap = 0; - -Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display) -{ - logTrace("Poller::Poller"); - - display_ = NULL; - shadowDisplayName_ = input -> getShadowDisplayName(); - - tmpBuffer_ = NULL; - - xtestExtension_ = -1; - shmExtension_ = -1; - randrExtension_ = -1; - damageExtension_ = -1; - - shadowDisplayUid_ = -1; - - image_ = NULL; - - shminfo_ = NULL; -} - -Poller::~Poller() -{ - logTrace("Poller::~Poller"); - - if (shmExtension_ == 1) - { - XShmDetach(display_, shminfo_); - XDestroyImage(image_); - shmdt(shminfo_ -> shmaddr); - shmctl(shminfo_ -> shmid, IPC_RMID, 0); - } - - if (shminfo_ != NULL) - { - delete shminfo_; - - shminfo_ = NULL; - } - - if (display_ != NULL) - { - XCloseDisplay(display_); - } - - if (tmpBuffer_ != NULL && shmExtension_ != -1 && damageExtension_ == 1) - { - XFree(tmpBuffer_); - - tmpBuffer_ = NULL; - } -} - -int Poller::init() -{ - logTrace("Poller::init"); - - if (display_ == NULL) - { - display_ = XOpenDisplay(shadowDisplayName_); - - setShadowDisplay(display_); - } - - logTest("Poller::init:" ,"Shadow display [%p] name [%s].", (Display *) display_, shadowDisplayName_); - - if (display_ == NULL) - { - logTest("Poller::init", "Failed to connect to display [%s].", shadowDisplayName_ ? shadowDisplayName_ : ""); - - return -1; - } - - setRootSize(); - - logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].", - width_, height_, depth_, bpl_, bpp_); - - xtestInit(); - - shmInit(); - - randrInit(); - - damageInit(); - - return CorePoller::init(); -} - -int Poller::updateShadowFrameBuffer(void) -{ - if (shmExtension_ == 1) - { - if (XShmGetImage(display_, DefaultRootWindow(display_), image_, 0, 0, AllPlanes) == 0) - { - logDebug("Poller::updateShadowFrameBuffer", "XShmGetImage failed!"); - - return -1; - } - } - else - { - image_ = XGetImage(display_, DefaultRootWindow(display_), 0, 0, width_, - height_, AllPlanes, ZPixmap); - - if (image_ == NULL) - { - logDebug("Poller::updateShadowFrameBuffer", "XGetImage failed!"); - - return -1; - } - } - - return 1; -} - -char *Poller::getRect(XRectangle r) -{ - logTrace("Poller::getRect"); - - logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].", - r.x, r.y, r.width, r.height); - - if (shmExtension_ == 1) - { - if (damageExtension_ == 1) - { - image_ -> width = r.width; - image_ -> height = r.height; - - image_ -> bytes_per_line = ROUNDUP((image_ -> bits_per_pixel * image_ -> width), image_ -> bitmap_pad); - - if (XShmGetImage(display_, DefaultRootWindow(display_), image_, r.x, r.y, AllPlanes) == 0) - { - logDebug("Poller::getRect", "XShmGetImage failed!"); - - return NULL; - } - - tmpBuffer_ = image_ -> data; - } - else - { - image_ -> width = r.width; - image_ -> height = r.height; - - image_ -> bytes_per_line = ROUNDUP((image_ -> bits_per_pixel * image_ -> width), image_ -> bitmap_pad); - - if (XShmGetImage(display_, DefaultRootWindow(display_), image_, r.x, r.y, AllPlanes) == 0) - { - logDebug("Poller::getRect", "XShmGetImage failed!"); - } - - tmpBuffer_ = image_ -> data; - } - } - else - { - if (tmpBuffer_) - { - XFree(tmpBuffer_); - tmpBuffer_ = NULL; - } - - image_ = XGetImage(display_, DefaultRootWindow(display_), r.x, r.y, r.width, r.height, AllPlanes, ZPixmap); - - if (image_ == NULL) - { - logError("Poller::getRect", ESET(ENOMSG)); - - return NULL; - } - - tmpBuffer_ = image_ -> data; - - if (image_ -> obdata) - { - XFree(image_ -> obdata); - } - - XFree(image_); - - image_ = NULL; - } - - return tmpBuffer_; -} - -void Poller::shmInit(void) -{ - int major, minor; - int pixmaps; - - logTest("Poller::shmInit", "Added shmExtension_ [%d].", shmExtension_); - - if (shmExtension_ >= 0) - { - logDebug("Poller::shmInit", "Called with shared memory already initialized."); - - if (shmInitTrap == 0) - { - return; - } - } - - if (shmExtension_ < 0 && NXShadowOptions.optionShmExtension == 0) - { - shmExtension_ = 0; - - logUser("Poller::shmInit: Disabling use of MIT-SHM extension.\n"); - - return; - } - - if (XShmQueryVersion(display_, &major, &minor, &pixmaps) == 0) - { - logDebug("Poller::shmInit", "MIT_SHM: Shared memory extension not available."); - - shmExtension_ = 0; - } - else - { - logDebug("Poller::shmInit", "MIT_SHM: Shared memory extension available."); - - if (shminfo_ != NULL) - { - destroyShmImage(); - } - - shminfo_ = (XShmSegmentInfo* ) new XShmSegmentInfo; - - if (shminfo_ == NULL) - { - logError("Poller::shmInit", ESET(ENOMEM)); - - shmExtension_ = 0; - - return; - } - - image_ = (XImage *)XShmCreateImage(display_, display_ -> screens[0].root_visual, depth_, ZPixmap, - NULL, shminfo_, width_, height_); - - if (image_ == NULL) - { - logError("Poller::shmInit", ESET(ENOMSG)); - - shmExtension_ = 0; - - return; - } - - shadowDisplayUid_ = NXShadowOptions.optionShadowDisplayUid; - - logDebug("Poller::shmInit", "Master X server uid [%d].", NXShadowOptions.optionShadowDisplayUid); - - shminfo_ -> shmid = shmget(IPC_PRIVATE, image_ -> bytes_per_line * image_ -> height, IPC_CREAT | 0666); - - if (shminfo_ -> shmid < 0) - { - logDebug("Poller::shmInit", "kernel id error."); - - shmExtension_ = 0; - - return; - } - - logDebug("Poller::shmInit", "Created shm segment with shmid [%d].", shminfo_ -> shmid); - - shminfo_ -> shmaddr = (char *)shmat(shminfo_ -> shmid, 0, 0); - - if (shminfo_ -> shmaddr < 0) - { - logWarning("Poller::shmInit", "Couldn't attach to shm segment."); - } - - logDebug("Poller::shmInit", "shminfo_ -> shmaddr [%p].", shminfo_ -> shmaddr); - - image_ -> data = shminfo_ -> shmaddr; - - shminfo_ -> readOnly = 0; - - if (XShmAttach(display_, shminfo_) == 0) - { - logDebug("Poller::shmInit", "XShmAttach failed."); - - shmExtension_ = 0; - - return; - } - - // - // Mark the shm segment to be destroyed after - // the last process detach. Let the X server - // complete the X_ShmAttach request, before. - // - - XSync(display_, 0); - - struct shmid_ds ds; - - shmctl(shminfo_ -> shmid, IPC_STAT, &ds); - - if (shadowDisplayUid_ != -1) - { - ds.shm_perm.uid = (ushort) shadowDisplayUid_; - } - else - { - logWarning("Poller::shmInit", "Couldn't set uid for shm segment."); - } - - ds.shm_perm.mode = 0600; - - shmctl(shminfo_ -> shmid, IPC_SET, &ds); - - shmctl(shminfo_ -> shmid, IPC_STAT, &ds); - - shmctl(shminfo_ -> shmid, IPC_RMID, 0); - - logDebug("Poller::shmInit", "Number of attaches to shm segment [%d] are [%d].\n", - shminfo_ -> shmid, (int) ds.shm_nattch); - - if (ds.shm_nattch > 2) - { - logWarning("Poller::shmInit", "More than two attaches to the shm segment."); - - destroyShmImage(); - - shmExtension_ = 0; - - return; - } - - shmExtension_ = 1; - } -} - -void Poller::keymapShadowInit(Display *display) -{ - int i, len; - CARD32 *map; - - if (NXShadowKeymap != NULL) - { - shadowMinKey = NXShadowKeymap -> minKeyCode; - shadowMaxKey = NXShadowKeymap -> maxKeyCode; - shadowMapWidth = NXShadowKeymap -> mapWidth; - - len = (shadowMaxKey - shadowMinKey + 1) * shadowMapWidth; - - map = (CARD32 *) NXShadowKeymap -> map; - - if (shadowKeymap != NULL) - { - free(shadowKeymap); - } - - shadowKeymap = (KeySym *) malloc(len * sizeof(KeySym)); - - if (shadowKeymap != NULL) - { - for (i = 0; i < len; i++) - { - shadowKeymap[i] = map[i]; - } - - shadowKeysyms = shadowKeymap; - } - } - - if (shadowKeysyms == NULL) - { - XDisplayKeycodes(display, &shadowMinKey, &shadowMaxKey); - - shadowKeysyms = XGetKeyboardMapping(display, shadowMinKey, shadowMaxKey - shadowMinKey + 1, - &shadowMapWidth); - } - - #ifdef DEBUG - if (shadowKeysyms != NULL) - { - for (i = 0; i < (shadowMaxKey - shadowMinKey + 1) * shadowMapWidth; i++) - { - if (i % shadowMapWidth == 0) - { - logDebug("Poller::keymapShadowInit", "keycode [%d]", (int) (i / shadowMapWidth)); - } - - logDebug("\tkeysym", " [%x] [%s]", (unsigned int) shadowKeysyms[i], XKeysymToString(shadowKeysyms[i])); - } - } - #endif -} - -void Poller::keymapMasterInit() -{ - XDisplayKeycodes(display_, &masterMinKey, &masterMaxKey); - - masterKeysyms = XGetKeyboardMapping(display_, masterMinKey, masterMaxKey - masterMinKey + 1, - &masterMapWidth); - - #ifdef DEBUG - if (masterKeysyms != NULL) - { - for (int i = 0; i < (masterMaxKey - masterMinKey + 1) * masterMapWidth; i++) - { - if (i % masterMapWidth == 0) - { - logDebug("Poller::keymapMasterInit", "keycode [%d]", (int) (i / masterMapWidth)); - } - - logDebug("\tkeysym", " [%x] [%s]", (unsigned int) masterKeysyms[i], XKeysymToString(masterKeysyms[i])); - } - } - #endif -} - -KeySym Poller::keymapKeycodeToKeysym(KeyCode keycode, KeySym *keysyms, - int minKey, int mapWidth, int col) -{ - int index = ((keycode - minKey) * mapWidth) + col; - return keysyms[index]; -} - -KeyCode Poller::keymapKeysymToKeycode(KeySym keysym, KeySym *keysyms, - int minKey, int maxKey, int mapWidth, int *col) -{ - for (int i = 0; i < (maxKey - minKey + 1) * mapWidth; i++) - { - if (keysyms[i] == keysym) - { - *col = i % mapWidth; - return i / mapWidth + minKey; - } - } - return 0; -} - -KeyCode Poller::translateKeysymToKeycode(KeySym keysym, int *col) -{ - KeyCode keycode; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - - if (keycode == 0) - { - if (((keysym >> 8) == 0) && (keysym >= XK_a) && (keysym <= XK_z)) - { - /* - * The master session has a Solaris keyboard. - */ - - keysym -= XK_a - XK_A; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - } - else if (keysym == XK_Shift_R) - { - keysym = XK_Shift_L; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - } - else if (keysym == XK_Shift_L) - { - keysym = XK_Shift_R; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - } - else if (keysym == XK_ISO_Level3_Shift) - { - keysym = XK_Mode_switch; - - if ((keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col)) == 0) - { - keysym = XK_Alt_R; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - } - } - else if (keysym == XK_Alt_R) - { - keysym = XK_ISO_Level3_Shift; - - if ((keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col)) == 0) - { - keysym = XK_Mode_switch; - - keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, col); - } - } - } - return keycode; -} - -Bool Poller::checkModifierKeys(KeySym keysym, Bool isKeyPress) -{ - switch (keysym) - { - case XK_Shift_L: - leftShiftOn = isKeyPress; - return True; - case XK_Shift_R: - rightShiftOn = isKeyPress; - return True; - case XK_Mode_switch: - modeSwitchOn = isKeyPress; - return True; - case XK_ISO_Level3_Shift: - level3ShiftOn = isKeyPress; - return True; - case XK_Alt_R: - altROn = isKeyPress; - return True; - default: - return False; - } -} - -void Poller::sendFakeModifierEvents(int pos, Bool skip) -{ - KeySym fakeKeysym; - int col; - - if ((!leftShiftOn && !rightShiftOn) && - (!modeSwitchOn && !level3ShiftOn && !altROn)) - { - if (pos == 1 || pos == 3) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - sentFakeLShiftPress = 1; - } - if (pos == 2 || pos == 3) - { - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - - if (fakeKeysym == 0) - { - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - sentFakeModeSwitchPress = 1; - } - else - { - sentFakeLevel3ShiftPress = 1; - } - - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - } - } - - else if ((leftShiftOn || rightShiftOn) && - (!modeSwitchOn && !level3ShiftOn && !altROn)) - { - if ((pos == 0 && !skip) || pos == 2) - { - if (leftShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeLShiftRelease = 1; - } - if (rightShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeRShiftRelease = 1; - } - } - if (pos == 2 || pos ==3) - { - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - - if (fakeKeysym == 0) - { - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - sentFakeModeSwitchPress = 1; - } - else - { - sentFakeLevel3ShiftPress = 1; - } - - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - } - } - - else if ((!leftShiftOn && !rightShiftOn) && - (modeSwitchOn || level3ShiftOn || altROn)) - { - if (pos == 1 || pos == 3) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - sentFakeLShiftPress = 1; - } - if (pos == 0 || pos == 1) - { - if (modeSwitchOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeModeSwitchRelease = 1; - } - if (level3ShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeLevel3ShiftRelease = 1; - } - if (altROn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeAltRRelease = 1; - } - } - } - - else if ((leftShiftOn || rightShiftOn) && - (modeSwitchOn || level3ShiftOn || altROn)) - { - if (pos == 0 || pos == 2) - { - if (leftShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeLShiftRelease = 1; - } - if (rightShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeRShiftRelease = 1; - } - } - if (pos == 0 || pos == 1) - { - if (modeSwitchOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeModeSwitchRelease = 1; - } - if (level3ShiftOn) - { - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeLevel3ShiftRelease = 1; - } - if (altROn) - { - fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - sentFakeAltRRelease = 1; - } - } - } -} - -void Poller::cancelFakeModifierEvents() -{ - KeySym fakeKeysym; - int col; - - if (sentFakeLShiftPress) - { - logTest("Poller::handleKeyboardEvent", "Fake Shift_L key press event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake Shift_L key release event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - - sentFakeLShiftPress = 0; - } - - if (sentFakeLShiftRelease) - { - logTest("Poller::handleKeyboardEvent", "Fake Shift_L key release event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake Shift_L key press event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - - sentFakeLShiftRelease = 0; - } - - if (sentFakeRShiftRelease) - { - logTest("Poller::handleKeyboardEvent", "Fake Shift_R key release event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake Shift_R key press event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - - sentFakeRShiftRelease = 0; - } - - if (sentFakeModeSwitchPress) - { - logTest("Poller::handleKeyboardEvent", "Fake Mode_switch key press event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake Mode_switch key release event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - - sentFakeModeSwitchPress = 0; - } - - if (sentFakeModeSwitchRelease) - { - logTest("Poller::handleKeyboardEvent", "Fake Mode_switch key release event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending Mode_switch key press event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - - sentFakeModeSwitchRelease = 0; - } - - if (sentFakeLevel3ShiftPress) - { - logTest("Poller::handleKeyboardEvent", "Fake ISO_Level3_Shift key press event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake ISO_Level3_Shift key release event"); - - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); - - sentFakeLevel3ShiftPress = 0; - } - - if (sentFakeLevel3ShiftRelease) - { - logTest("Poller::handleKeyboardEvent", "Fake ISO_Level3_Shift key release event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake ISO_Level3_Shift key press event"); - - fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - - sentFakeLevel3ShiftRelease = 0; - } - - if (sentFakeAltRRelease) - { - logTest("Poller::handleKeyboardEvent", "Fake XK_Alt_R key release event has been sent"); - logTest("Poller::handleKeyboardEvent", "Sending fake XK_Alt_R key press event"); - - fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, - masterMaxKey, masterMapWidth, &col); - XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); - - sentFakeAltRRelease = 0; - } -} - -Bool Poller::keyIsDown(KeyCode keycode) -{ - KeyPressedRec *downKey; - - downKey = shadowKeyPressedPtr; - - while (downKey) - { - if (downKey -> keyRcvd == keycode) - { - return True; - } - downKey = downKey -> next; - } - - return False; -} - -void Poller::addKeyPressed(KeyCode received, KeyCode sent) -{ - KeyPressedRec *downKey; - - if (!keyIsDown(received)) - { - if (shadowKeyPressedPtr == NULL) - { - shadowKeyPressedPtr = (KeyPressedRec *) malloc(sizeof(KeyPressedRec)); - - shadowKeyPressedPtr -> keyRcvd = received; - shadowKeyPressedPtr -> keySent = sent; - shadowKeyPressedPtr -> next = NULL; - } - else - { - downKey = shadowKeyPressedPtr; - - while (downKey -> next != NULL) - { - downKey = downKey -> next; - } - - downKey -> next = (KeyPressedRec *) malloc(sizeof(KeyPressedRec)); - - downKey -> next -> keyRcvd = received; - downKey -> next -> keySent = sent; - downKey -> next -> next = NULL; - } - } -} - -KeyCode Poller::getKeyPressed(KeyCode received) -{ - KeyCode sent; - KeyPressedRec *downKey; - KeyPressedRec *tempKey; - - if (shadowKeyPressedPtr != NULL) - { - if (shadowKeyPressedPtr -> keyRcvd == received) - { - sent = shadowKeyPressedPtr -> keySent; - - tempKey = shadowKeyPressedPtr; - shadowKeyPressedPtr = shadowKeyPressedPtr -> next; - free(tempKey); - - return sent; - } - else - { - downKey = shadowKeyPressedPtr; - - while (downKey -> next != NULL) - { - if (downKey -> next -> keyRcvd == received) - { - sent = downKey -> next -> keySent; - - tempKey = downKey -> next; - downKey -> next = downKey -> next -> next; - free(tempKey); - - return sent; - } - else - { - downKey = downKey -> next; - } - } - } - } - return 0; -} - -void Poller::handleKeyboardEvent(Display *display, XEvent *event) -{ - if (xtestExtension_ == 0 || display_ == 0) - { - return; - } - - logTest("Poller::handleKeyboardEvent", "Handling event at [%p]", event); - -#ifdef TRANSLATE_ALWAYS - - KeyCode keycode; - KeySym keysym; - - int col = 0; - - Bool isKeyPress = False; - Bool isModifier = False; - Bool isShiftComb = False; - Bool skip = False; - - if (event -> type == KeyPress) - { - isKeyPress = True; - } - - if (shadowKeysyms == NULL) - { - keymapShadowInit(event -> xkey.display); - } - - if (masterKeysyms == NULL) - { - keymapMasterInit(); - } - - if (shadowKeysyms == NULL || masterKeysyms == NULL) - { - logTest("Poller::handleKeyboardEvent", "Unable to initialize keymaps. Do not translate"); - - keycode = event -> xkey.keycode; - - goto SendKeycode; - } - - keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, - shadowMinKey, shadowMapWidth, 0); - - isModifier = checkModifierKeys(keysym, isKeyPress); - - if (event -> type == KeyRelease) - { - KeyCode keycodeToSend; - - keycodeToSend = getKeyPressed(event -> xkey.keycode); - - if (keycodeToSend) - { - keycode = keycodeToSend; - - goto SendKeycode; - } - } - - /* - * Convert case for Solaris keyboard. - */ - - if (((keysym >> 8) == 0) && (keysym >= XK_A) && (keysym <= XK_Z)) - { - if (!leftShiftOn && !rightShiftOn) - { - keysym += XK_a - XK_A; - } - else - { - skip = True; - } - } - - if (!isModifier) - { - if ((leftShiftOn || rightShiftOn) && - (!modeSwitchOn && !level3ShiftOn && !altROn) && - !skip) - { - KeySym tempKeysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, - shadowMinKey, shadowMapWidth, 1); - - if (tempKeysym == 0) - { - isShiftComb = True; - } - else - { - keysym = tempKeysym; - } - } - else if ((!leftShiftOn && !rightShiftOn) && - (modeSwitchOn || level3ShiftOn || altROn)) - { - keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, - shadowMinKey, shadowMapWidth, 2); - } - else if ((leftShiftOn || rightShiftOn) && - (modeSwitchOn || level3ShiftOn || altROn)) - { - keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, - shadowMinKey, shadowMapWidth, 3); - } - } - - if (keysym == 0) - { - logTest("Poller::handleKeyboardEvent", "Null keysym. Return"); - - return; - } - - logTest("Poller::handleKeyboardEvent", "keysym [%x] [%s]", - (unsigned int)keysym, XKeysymToString(keysym)); - - if (keysym == XK_Mode_switch) - { - keysym = XK_ISO_Level3_Shift; - } - - keycode = translateKeysymToKeycode(keysym, &col); - - if (keycode == 0) - { - logTest("Poller::handleKeyboardEvent", "No keycode found for keysym [%x] [%s]. Return", - (unsigned int)keysym, XKeysymToString(keysym)); - return; - } - - logTest("Poller::handleKeyboardEvent", "keycode [%d] translated into keycode [%d]", - (int)event -> xkey.keycode, (unsigned int)keycode); - - if (event -> type == KeyPress) - { - addKeyPressed(event -> xkey.keycode, keycode); - } - - /* - * Send fake modifier events. - */ - - if (!isModifier && isShiftComb == False) - { - sendFakeModifierEvents(col, ((keysym >> 8) == 0) && (keysym >= XK_A) && (keysym <= XK_Z)); - } - -SendKeycode: - - /* - * Send the event. - */ - - XTestFakeKeyEvent(display_, keycode, isKeyPress, 0); - - /* - * Check if fake modifier events have been sent. - */ - - cancelFakeModifierEvents(); - -#else // TRANSLATE_ALWAYS - - // - // Use keysyms to translate keycodes across different - // keyboard models. Unuseful when both keyboards have - // same keycodes (e.g. both are pc keyboards). - // - - #ifdef TRANSLATE_KEYCODES - - KeyCode keycode = XKeysymToKeycode(display_, XK_A); - - if (XKeysymToKeycode(event -> xkey.display, XK_A) != keycode) - { - KeySym keysym = XKeycodeToKeysym(event -> xkey.display, event -> xkey.keycode, 0); - - if (keysym == XK_Mode_switch || keysym == XK_ISO_Level3_Shift) - { - logUser("Poller::handleKeyboardEvent: keysym [%x].\n", (unsigned int)keysym); - - if (XKeycodeToKeysym(display_, 113, 0) == XK_ISO_Level3_Shift || - (XKeycodeToKeysym(display_, 124, 0) == XK_ISO_Level3_Shift)) - { - event -> xkey.keycode = 113; - } - else - { - event -> xkey.keycode = XKeysymToKeycode(display_, XK_Mode_switch); - } - - logUser("Poller::handleKeyboardEvent: keycode translated to [%x].\n", (unsigned int)event -> xkey.keycode); - } - else - { - event -> xkey.keycode = XKeysymToKeycode(display_, keysym); - } - } - - #endif // TRANSLATE_KEYCODES - - if (event -> type == KeyPress) - { - XTestFakeKeyEvent(display_, event -> xkey.keycode, 1, 0); - } - else if (event -> type == KeyRelease) - { - XTestFakeKeyEvent(display_, event -> xkey.keycode, 0, 0); - } - -#endif // TRANSLATE_ALWAYS -} - -void Poller::handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) -{ - KeyCode keycode; - int col; - - if (masterKeysyms == NULL) - { - keymapMasterInit(); - } - - if (masterKeysyms == NULL) - { - logTest("Poller::handleWebKeyboardEvent", "Unable to initialize keymap"); - - return; - } - - keycode = translateKeysymToKeycode(keysym, &col); - - if (keycode == 0) - { - logTest("Poller::handleKeyboardEvent", "No keycode found for keysym [%x] [%s]. Return", - (unsigned int)keysym, XKeysymToString(keysym)); - return; - } - - logTest("Poller::handleKeyboardEvent", "keysym [%x] [%s] translated into keycode [%x]", - (unsigned int)keysym, XKeysymToString(keysym), (unsigned int)keycode); - - /* - * Send fake modifier events. - */ - - if (!checkModifierKeys(keysym, isKeyPress)) - { - sendFakeModifierEvents(col, False); - } - - /* - * Send the event. - */ - - XTestFakeKeyEvent(display_, keycode, isKeyPress, 0); - - /* - * Check if fake modifier events have been sent. - */ - - cancelFakeModifierEvents(); - -} - -void Poller::handleMouseEvent(Display *display, XEvent *event) -{ - if (xtestExtension_ == 0 || display_ == 0) - { - return; - } - - if (event -> type == MotionNotify) - { - XTestFakeMotionEvent(display_, 0, event -> xmotion.x, event -> xmotion.y, 0); - } - else if (event -> type == ButtonPress) - { - XTestFakeButtonEvent(display_, event -> xbutton.button, True, 0); - } - else if (event -> type == ButtonRelease) - { - XTestFakeButtonEvent(display_, event -> xbutton.button, False, 0); - } - - XFlush(display_); -} - -void Poller::setRootSize(void) -{ - width_ = WidthOfScreen(DefaultScreenOfDisplay(display_)); - height_ = HeightOfScreen(DefaultScreenOfDisplay(display_)); - depth_ = DefaultDepth(display_, DefaultScreen(display_)); - - if (depth_ == 8) bpp_ = 1; - else if (depth_ == 16) bpp_ = 2; - else bpp_ = 4; - - bpl_ = width_ * bpp_; -} - -void Poller::destroyShmImage(void) -{ - XShmDetach(display_, shminfo_); - XDestroyImage(image_); - image_ = NULL; - - shmdt(shminfo_ -> shmaddr); - shmctl(shminfo_ -> shmid, IPC_RMID, 0); - - delete shminfo_; - shminfo_ = NULL; -} - -void Poller::xtestInit(void) -{ - int eventBase; - int errorBase; - int versionMajor; - int versionMinor; - int result; - - xtestExtension_ = 0; - - result = XTestQueryExtension(display_, &eventBase, &errorBase, &versionMajor, &versionMinor); - - if (result == 0) - { - xtestExtension_ = 0; - - logWarning("Poller::xtestInit", "Failed while querying for XTEST extension."); - } - else - { - logDebug("Poller::xtestInit", "XTEST version %d.%d.", versionMajor, versionMinor); - - xtestExtension_ = 1; - } - - // - // Make this client impervious to grabs. - // - - if (xtestExtension_ == 1) - { - XTestGrabControl(display_, 1); - } -} - -void Poller::randrInit(void) -{ - int randrEventBase; - int randrErrorBase; - - if (XRRQueryExtension(display_, &randrEventBase, &randrErrorBase) == 0) - { - logWarning("Poller::randrInit", "Randr extension not supported on this " - "display."); - - randrExtension_ = 0; - - return; - } - - XRRSelectInput(display_, DefaultRootWindow(display_), - RRScreenChangeNotifyMask); - - randrEventBase_ = randrEventBase; - - randrExtension_ = 1; - - return; -} - -void Poller::damageInit(void) -{ - int damageMajorVersion = 0; - int damageMinorVersion = 0; - - int damageEventBase = 0; - int damageErrorBase = 0; - - if (damageExtension_ >= 0) - { - logDebug("Poller::damageInit", "Called with damage already initialized."); - } - - if (damageExtension_ == 0) - { - logDebug("Poller::damageInit", "Damage disabled. Skip initialization."); - - return; - } - - if (damageExtension_ < 0 && NXShadowOptions.optionDamageExtension == 0) - { - damageExtension_ = 0; - - logUser("Poller::damageInit: Disabling use of DAMAGE extension.\n"); - - return; - } - - damageExtension_ = 0; - - mirrorChanges_ = 0; - - if (XDamageQueryExtension(display_, &damageEventBase, &damageErrorBase) == 0) - { - logUser("Poller::damageInit: DAMAGE not supported.\n"); - - return; - } - #ifdef DEBUG - else - { - fprintf(stderr, "Poller::damageInit: DAMAGE supported. " - "Event base [%d] error base [%d].\n", damageEventBase, damageErrorBase); - } - #endif - - damageEventBase_ = damageEventBase; - - if (XDamageQueryVersion(display_, &damageMajorVersion, &damageMinorVersion) == 0) - { - logWarning("Poller::damageInit", "Error on querying DAMAGE version.\n"); - - damageExtension_ = 0; - - return; - } - #ifdef DEBUG - else - { - fprintf(stderr, "Poller::damageInit: DAMAGE version %d.%d.\n", - damageMajorVersion, damageMinorVersion); - } - #endif - - damage_ = XDamageCreate(display_, DefaultRootWindow(display_), XDamageReportRawRectangles); - - damageExtension_= 1; - - mirror_ = 1; - - return; -} - -void Poller::getEvents(void) -{ - XEvent X; - - if (damageExtension_ == 1) - { - XDamageSubtract(display_, damage_, None, None); - } - - XSync(display_, 0); - - while (XCheckIfEvent(display_, &X, anyEventPredicate, NULL) == 1) - { - if (randrExtension_ == 1 && (X.type == randrEventBase_ + RRScreenChangeNotify || X.type == ConfigureNotify)) - { - XRRUpdateConfiguration(&X); - - handleRRScreenChangeNotify(&X); - - continue; - } - - if (damageExtension_ == 1 && X.type == damageEventBase_ + XDamageNotify) - { - handleDamageNotify(&X); - } - } - - if (damageExtension_ == 1) - { - updateDamagedAreas(); - } - - XFlush(display_); -} - -void Poller::handleRRScreenChangeNotify(XEvent *X) -{ - return; -} - -void Poller::handleDamageNotify(XEvent *X) -{ - XDamageNotifyEvent *e = (XDamageNotifyEvent *) X; - - // - // e->drawable is the window ID of the damaged window - // e->geometry is the geometry of the damaged window - // e->area is the bounding rect for the damaged area - // e->damage is the damage handle returned by XDamageCreate() - // - - #ifdef DEBUG - fprintf(stderr, "handleDamageNotify: drawable [%d] damage [%d] geometry [%d][%d][%d][%d] area [%d][%d][%d][%d].\n", - (int) e -> drawable, (int) e -> damage, e -> geometry.x, e -> geometry.y, - e -> geometry.width, e -> geometry.height, e -> area.x, e -> area.y, - e -> area.width, e -> area.height); - #endif - - XRectangle rectangle = {e -> area.x, e -> area.y, e -> area.width, e -> area.height}; - - XUnionRectWithRegion(&rectangle, lastUpdatedRegion_, lastUpdatedRegion_); - - mirrorChanges_ = 1; - - return; -} - -void Poller::updateDamagedAreas(void) -{ - BOX *boxPtr; - - XRectangle rectangle; - - int i; - int y; - - for (i = 0; i < lastUpdatedRegion_ -> numRects; i++) - { - boxPtr = lastUpdatedRegion_ -> rects + i; - - if (shmExtension_ == 1) - { - image_ -> width = boxPtr -> x2 - boxPtr -> x1; - image_ -> height = boxPtr -> y2 - boxPtr -> y1; - image_ -> bytes_per_line = - ROUNDUP((image_ -> bits_per_pixel * image_ -> width), - image_ -> bitmap_pad); - - if (XShmGetImage(display_, DefaultRootWindow(display_), image_, - boxPtr -> x1, boxPtr -> y1, AllPlanes) == 0) - { - logDebug("Poller::updateDamagedAreas", "XShmGetImage failed!"); - - return; - } - } - else if (shmExtension_ == 0) - { - image_ = XGetImage(display_, DefaultRootWindow(display_), boxPtr -> x1, - boxPtr -> y1, boxPtr -> x2 - boxPtr -> x1, - boxPtr -> y2 - boxPtr -> y1, AllPlanes, - ZPixmap); - - if (image_ == NULL) - { - logDebug("Poller::updateDamagedAreas", "XGetImage failed!"); - - return; - } - - image_ -> width = boxPtr -> x2 - boxPtr -> x1; - image_ -> height = boxPtr -> y2 - boxPtr -> y1; - image_ -> bytes_per_line = - ROUNDUP((image_ -> bits_per_pixel * image_ -> width), - image_ -> bitmap_pad); - } - - rectangle.height = 1; - rectangle.width = image_ -> width; - rectangle.x = boxPtr -> x1; - rectangle.y = boxPtr -> y1; - - for (y = 0; y < image_ -> height; y++) - { - update(image_ -> data + y * image_ -> bytes_per_line, rectangle); - - rectangle.y++; - } - - if (shmExtension_ != 1) - { - XDestroyImage(image_); - - image_ = NULL; - } - } - - return; -} - -void Poller::getScreenSize(int *w, int *h) -{ - *w = WidthOfScreen(DefaultScreenOfDisplay(display_)); - *h = HeightOfScreen(DefaultScreenOfDisplay(display_)); -} - -void Poller::setScreenSize(int *w, int *h) -{ - setRootSize(); - - shmInitTrap = 1; - shmInit(); - shmInitTrap = 0; - - *w = width_; - *h = height_; - - logDebug("Poller::setScreenSize", "New size of screen [%d, %d]", width_, height_); -} - -int anyEventPredicate(Display *display, XEvent *event, XPointer parameter) -{ - return 1; -} - -#endif /* !defined(__CYGWIN32__) && !defined(WIN32) */ diff --git a/nxcompshad/X11.h b/nxcompshad/X11.h deleted file mode 100644 index 87dd31fea..000000000 --- a/nxcompshad/X11.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -/* Copyright (c) 2008-2014 Oleksandr Shneyder */ -/* Copyright (c) 2014-2016 Ulrich Sibiller */ -/* Copyright (c) 2014-2016 Mihai Moldovan */ -/* Copyright (c) 2011-2016 Mike Gabriel */ -/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -/* */ -/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -/* are copyright of the aforementioned persons and companies. */ -/* */ -/* Redistribution and use of the present software is allowed according */ -/* to terms specified in the file LICENSE which comes in the source */ -/* distribution. */ -/* */ -/* All rights reserved. */ -/* */ -/* NOTE: This software has received contributions from various other */ -/* contributors, only the core maintainers and supporters are listed as */ -/* copyright holders. Please contact us, if you feel you should be listed */ -/* as copyright holder, as well. */ -/* */ -/**************************************************************************/ - -#ifndef X11Poller_H -#define X11Poller_H - -#include -#include -#include "X11/include/Xdamage_nxcompshad.h" -#include "X11/include/Xrandr_nxcompshad.h" - -#include "Core.h" - -class Poller : public CorePoller -{ - public: - - Poller(Input *, Display *display, int = 0); - - ~Poller(); - - int init(); - - void setRootSize(); - - void destroyShmImage(); - - void getEvents(void); - - void getScreenSize(int *width, int *height); - - void setScreenSize(int *width, int *height); - - private: - - Display *display_; - - char *shadowDisplayName_; - - int shadowDisplayUid_; - - char *tmpBuffer_; - - char xtestExtension_; - - char shmExtension_; - - char randrExtension_; - - int randrEventBase_; - - char damageExtension_; - - int damageEventBase_; - - Damage damage_; - - Region repair_; - - char damageChanges_; - - XShmSegmentInfo *shminfo_; - - XImage *image_; - - int updateShadowFrameBuffer(void); - - char *getRect(XRectangle); - - void keymapShadowInit(Display *display); - - void keymapMasterInit(); - - KeySym keymapKeycodeToKeysym(KeyCode keycode, KeySym *keysyms, - int minKey, int per, int col); - - KeyCode keymapKeysymToKeycode(KeySym keysym, KeySym *keysyms, - int minKey, int maxKey, int per, int *col); - - KeyCode translateKeysymToKeycode(KeySym keysym, int *col); - - Bool checkModifierKeys(KeySym keysym, Bool isKeyPress); - - void sendFakeModifierEvents(int pos, Bool skip); - - void cancelFakeModifierEvents(); - - Bool keyIsDown(KeyCode keycode); - - void addKeyPressed(KeyCode received, KeyCode sent); - - KeyCode getKeyPressed(KeyCode received); - - void handleKeyboardEvent(Display *display, XEvent *); - - void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress); - - void handleMouseEvent(Display *, XEvent *); - - void xtestInit(void); - - void shmInit(void); - - void randrInit(void); - - void damageInit(void); - - void handleRRScreenChangeNotify(XEvent *); - - void handleDamageNotify(XEvent *); - - void updateDamagedAreas(void); -}; - -int anyEventPredicate(Display *display, XEvent *event, XPointer parameter); - -#endif /* X11Poller_H */ diff --git a/nxcompshad/X11/include/XTest_nxcompshad.h b/nxcompshad/X11/include/XTest_nxcompshad.h deleted file mode 100644 index 91a2ba40b..000000000 --- a/nxcompshad/X11/include/XTest_nxcompshad.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - -Copyright 1992, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ - -#ifndef _XTEST_H_ -#define _XTEST_H_ - -#include - -_XFUNCPROTOBEGIN - -Bool XTestQueryExtension( - Display* /* dpy */, - int* /* event_basep */, - int* /* error_basep */, - int* /* majorp */, - int* /* minorp */ -); - -extern int XTestFakeKeyEvent( - Display* /* dpy */, - unsigned int /* keycode */, - Bool /* is_press */, - unsigned long /* delay */ -); - -extern int XTestFakeButtonEvent( - Display* /* dpy */, - unsigned int /* button */, - Bool /* is_press */, - unsigned long /* delay */ -); - -extern int XTestFakeMotionEvent( - Display* /* dpy */, - int /* screen */, - int /* x */, - int /* y */, - unsigned long /* delay */ -); - -extern int XTestGrabControl( - Display* /* dpy */, - Bool /* impervious */ -); - -_XFUNCPROTOEND - -#endif diff --git a/nxcompshad/X11/include/Xdamage_nxcompshad.h b/nxcompshad/X11/include/Xdamage_nxcompshad.h deleted file mode 100644 index cae3e1c67..000000000 --- a/nxcompshad/X11/include/Xdamage_nxcompshad.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright © 2003 Keith Packard - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file is a reduced version of the header file of - * - * - * This copy of code has been introduced to allow a clear namespace - * separation between and header files. - * - * This version of the Xdamage library header file only contains symbols - * required by nxcompshad and strictly avoids indirectly including - * from an X11 library that is also shipped in nx-X11/lib/. - * - * When using instead for inclusion in - * nxcompshad, it will attempt pulling in the - * header which in turn will include . However, the headers of - * the same name from should be used instead. - * - * FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this - * hack can be removed. - * - * 2015/06/26, Mike Gabriel - */ - - -#ifndef _XDAMAGE_H_ -#define _XDAMAGE_H_ - -#include -#include - -/* from */ -typedef XID XserverRegion; - -#define XDAMAGE_1_1_INTERFACE - -typedef XID Damage; - -typedef struct { - int type; /* event base */ - unsigned long serial; - Bool send_event; - Display *display; - Drawable drawable; - Damage damage; - int level; - Bool more; /* more events will be delivered immediately */ - Time timestamp; - XRectangle area; - XRectangle geometry; -} XDamageNotifyEvent; - -_XFUNCPROTOBEGIN - -Bool XDamageQueryExtension (Display *dpy, - int *event_base_return, - int *error_base_return); - -Status XDamageQueryVersion (Display *dpy, - int *major_version_return, - int *minor_version_return); - -Damage -XDamageCreate (Display *dpy, Drawable drawable, int level); - -void -XDamageSubtract (Display *dpy, Damage damage, - XserverRegion repair, XserverRegion parts); - -_XFUNCPROTOEND - -#endif /* _XDAMAGE_H_ */ diff --git a/nxcompshad/X11/include/Xrandr_nxcompshad.h b/nxcompshad/X11/include/Xrandr_nxcompshad.h deleted file mode 100644 index 4feb01685..000000000 --- a/nxcompshad/X11/include/Xrandr_nxcompshad.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright © 2000 Compaq Computer Corporation, Inc. - * Copyright © 2002 Hewlett-Packard Company, Inc. - * Copyright © 2006 Intel Corporation - * Copyright © 2008 Red Hat, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - * - * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. - * Keith Packard, Intel Corporation - */ - -/* - * This file is a reduced version of the header file of - * - * - * This copy of code has been introduced to allow a clear namespace - * separation between and header files. - * - * This version of the Xrandr library header file only contains symbols - * required by nxcompshad and strictly avoids indirectly including - * from an X11 library that is also shipped in nx-X11/lib/. - * - * When using instead for inclusion in - * nxcompshad, it will attempt pulling in the - * header which in turn will include . However, the headers of - * the same name from should be used instead. - * - * FIXME: Once the nxagent Xserver starts using libXrender from X.Org, this - * hack can be removed. - * - * 2015/06/26, Mike Gabriel - */ - -#ifndef _XRANDR_H_ -#define _XRANDR_H_ - -/* from */ -#define RRScreenChangeNotify 0 -#define RRScreenChangeNotifyMask (1L << 0) - -#include - -_XFUNCPROTOBEGIN - -/* internal representation is private to the library */ -typedef struct _XRRScreenConfiguration XRRScreenConfiguration; - -Bool XRRQueryExtension (Display *dpy, - int *event_base_return, - int *error_base_return); - -void XRRSelectInput(Display *dpy, Window window, int mask); - - -/* - * intended to take RRScreenChangeNotify, or - * ConfigureNotify (on the root window) - * returns 1 if it is an event type it understands, 0 if not - */ -int XRRUpdateConfiguration(XEvent *event); -_XFUNCPROTOEND - -#endif /* _XRANDR_H_ */ diff --git a/nxcompshad/configure.ac b/nxcompshad/configure.ac new file mode 100644 index 000000000..b3abf0efb --- /dev/null +++ b/nxcompshad/configure.ac @@ -0,0 +1,53 @@ +dnl *************************************************************************** +dnl *** configure.ac for nxcompshad *** +dnl *************************************************************************** + +m4_define([nxcompshad_version], m4_esyscmd([tr -d '\n' < VERSION])) + +# Initialize Autoconf +AC_PREREQ(2.60) + +AC_INIT([libXcompshad], [nxcompshad_version], [https://github.com/ArcticaProject/nx-libs/issues]) +AC_PROG_CXX +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) + +AM_INIT_AUTOMAKE([foreign no-dist-gzip dist-xz]) + +# Initialize libtool +AC_PROG_LIBTOOL + +COMPSHAD_VERSION=nxcompshad_version +AC_SUBST([COMPSHAD_VERSION]) + +LT_COMPSHAD_VERSION=[`echo $COMPSHAD_VERSION | sed -r -e 's/^([0-9]+\.[0-9]+\.[0-9]+).*$/\1/' -e 's/\./:/g'`] +AC_SUBST([LT_COMPSHAD_VERSION]) + +PKG_CHECK_MODULES(Xext, xext) +PKG_CHECK_MODULES(Xdamage, xdamage) +PKG_CHECK_MODULES(Xrandr, xrandr) +PKG_CHECK_MODULES(Xtst, xtst) + +# Upstream's pkg.m4 (since 0.27) offers this now, but define our own +# compatible version in case the local version of pkgconfig isn't new enough. +# https://bugs.freedesktop.org/show_bug.cgi?id=48743 +m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], + [AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], + [install directory for nxcompshad.pc pkg-config file])], + [],[with_pkgconfigdir='$(libdir)/pkgconfig']) + AC_SUBST([pkgconfigdir], [${with_pkgconfigdir}])]) + +AC_LANG([C++]) +NX_COMPILER_BRAND +NX_COMPILER_FLAGS + +AC_CONFIG_FILES([ +Makefile +src/Makefile +nxcompshad.pc +]) + +AC_OUTPUT diff --git a/nxcompshad/configure.in b/nxcompshad/configure.in deleted file mode 100644 index bb9286e3d..000000000 --- a/nxcompshad/configure.in +++ /dev/null @@ -1,307 +0,0 @@ -dnl /**************************************************************************/ -dnl /* */ -dnl /* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ -dnl /* Copyright (c) 2008-2014 Oleksandr Shneyder */ -dnl /* Copyright (c) 2014-2016 Ulrich Sibiller */ -dnl /* Copyright (c) 2014-2016 Mihai Moldovan */ -dnl /* Copyright (c) 2011-2016 Mike Gabriel */ -dnl /* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ -dnl /* */ -dnl /* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ -dnl /* are copyright of the aforementioned persons and companies. */ -dnl /* */ -dnl /* Redistribution and use of the present software is allowed according */ -dnl /* to terms specified in the file LICENSE which comes in the source */ -dnl /* distribution. */ -dnl /* */ -dnl /* All rights reserved. */ -dnl /* */ -dnl /* NOTE: This software has received contributions from various other */ -dnl /* contributors, only the core maintainers and supporters are listed as */ -dnl /* copyright holders. Please contact us, if you feel you should be listed */ -dnl /* as copyright holder, as well. */ -dnl /* */ -dnl /**************************************************************************/ - - -dnl Process this file with autoconf to produce a configure script. - -dnl Prolog - -AC_INIT(Shadow.h) -AC_PREREQ(2.13) - -pkgconfigdir=${libdir}/pkgconfig -AC_SUBST(pkgconfigdir) - -dnl Reset default compilation flags. - -if test "x$CXXFLAGS" == "x"; then - CXXFLAGS="-O3" -fi -if test "x$CPPFLAGS" == "x"; then - CPPFLAGS="-O3" -fi - -dnl Reset default linking directives. - -LIBSTATIC="" -LIBSHARED="" - -dnl Prefer headers and libraries from nx-X11, if present. - -if test -d "../nx-X11/exports/include" ; then - CXXFLAGS="$CXXFLAGS -I../nx-X11/exports/include" - LIBS="-L../nx-X11/exports/lib" -fi - -dnl Check whether --with-ipaq was given. - -if test "${with_ipaq}" = yes; then - echo -e "enabling IPAQ configuration" - CXX="arm-linux-c++" - CC="arm-linux-gcc" - unset ac_cv_prog_armcxx - unset ac_cv_prog_armcc - unset ac_cv_prog_CXXCPP - AC_CHECK_PROG([armcxx],["$CXX"],[yes],[no],[$PATH]) - AC_CHECK_PROG([armcc],["$CC"],[yes],[no],[$PATH]) - if test $armcxx = "yes" && test $armcc = "yes" ; then - ac_cv_prog_CXX="$CXX" - ac_cv_prog_CC="$CC" - else - AC_MSG_ERROR(installation or configuration problem: I cannot find compiler for arm-linux) - fi -else - unset ac_cv_prog_CXX - unset ac_cv_prog_CC - unset ac_cv_prog_CXXCPP -fi - -dnl Check for programs. - -AC_PROG_CXX -AC_PROG_CC -AC_LANG_CPLUSPLUS - -dnl Check whether option -Wno-deprecated -dnl is needed by GCC compiler. - -AC_MSG_CHECKING([whether compiler needs -Wno-deprecated]) -gcc_version=`${CC} --version | grep 'gcc (GCC) [[3-4]].' | head -n 1` -case "${gcc_version}" in - gcc*) - AC_MSG_RESULT([yes]) - CXXFLAGS="$CXXFLAGS -Wno-deprecated" - CPPFLAGS="$CPPFLAGS -Wno-deprecated" - ;; - - *) - AC_MSG_RESULT([no]) - ;; -esac - -AC_MSG_CHECKING([whether compiler accepts -Wmissing-declarations and -Wnested-externs]) -gcc_version=`${CC} --version | grep 'gcc (GCC) [[3-4]].' | head -n 1` -case "${gcc_version}" in - gcc*) - AC_MSG_RESULT([no]) - ;; - - *) - AC_MSG_RESULT([yes]) - CXXFLAGS="$CXXFLAGS -Wmissing-declarations" - CPPFLAGS="$CPPFLAGS -Wmissing-declarations" - ;; -esac - -dnl Check for BSD compatible install. - -AC_PROG_INSTALL - -dnl Check for extra header files. - -AC_PATH_XTRA - -dnl Custom addition. - -ac_help="$ac_help - --with-symbols give -g flag to compiler to produce debug symbols - --with-info define INFO at compile time to get basic log output - --with-valgrind clean up allocated buffers to avoid valgrind warnings - --with-version use this version for produced libraries - - --with-static-jpeg enable static linking of JPEG library - --with-static-z enable static linking of Z library" - -dnl Check to see if we're running under Cygwin32. - -AC_DEFUN(nxconf_CYGWIN32, -[AC_CACHE_CHECK(for Cygwin32 environment, nxconf_cv_cygwin32, -[AC_TRY_COMPILE(,[return __CYGWIN32__;], -nxconf_cv_cygwin32=yes, nxconf_cv_cygwin32=no) -rm -f conftest*]) -CYGWIN32= -test "$nxconf_cv_cygwin32" = yes && CYGWIN32=yes]) -nxconf_CYGWIN32 - -dnl Cygwin32 requires the stdc++ library explicitly linked. - -if test "$CYGWIN32" = yes; then - LIBS="$LIBS -lstdc++ -lcygipc -lgdi32" -fi - -dnl Check for Darwin environment. - -AC_DEFUN(nxconf_DARWIN, -[AC_CACHE_CHECK(for Darwin environment, nxconf_cv_darwin, -[AC_TRY_COMPILE(,[return __APPLE__;], -nxconf_cv_darwin=yes, nxconf_cv_darwin=no) -rm -f conftest*]) -DARWIN= -test "$nxconf_cv_darwin" = yes && DARWIN=yes]) -nxconf_DARWIN - -dnl Check to see if we're running under Solaris. - -AC_DEFUN(nxconf_SUN, -[AC_CACHE_CHECK(for Solaris environment, nxconf_cv_sun, -[AC_TRY_COMPILE(,[return __sun;], -nxconf_cv_sun=yes, nxconf_cv_sun=no) -rm -f conftest*]) -SUN= -test "$nxconf_cv_sun" = yes && SUN=yes]) -nxconf_SUN - -dnl Check to see if we're running under FreeBSD. - -AC_DEFUN(nxconf_FreeBSD, -[AC_CACHE_CHECK(for FreeBSD environment, nxconf_cv_freebsd, -[AC_TRY_COMPILE(,[return __FreeBSD__;], -nxconf_cv_freebsd=yes, nxconf_cv_freebsd=no) -rm -f conftest*]) -FreeBSD= -test "$nxconf_cv_freebsd" = yes && FreeBSD=yes]) -nxconf_FreeBSD - -dnl Build PIC libraries. - -if test "$CYGWIN32" != yes -a "$DARWIN" != yes; then - CXXFLAGS="$CXXFLAGS -fPIC" - CFLAGS="$CFLAGS -fPIC" -fi - -dnl Solaris requires the socket and gcc_s libs explicitly linked. -dnl Note also that headers from default /usr/openwin/include/X11 -dnl cause a warning due to pragma in Xmd.h. - -if test "$SUN" = yes; then - LIBS="$LIBS -L/usr/sfw/lib -lsocket " - CXXFLAGS="$CXXFLAGS -I/usr/sfw/include" -fi - -dnl On FreeBSD search libraries and includes under /usr/local. - -if test "$FreeBSD" = yes; then - LIBS="$LIBS -L/usr/local/lib" - CXXFLAGS="$CXXFLAGS -I/usr/local/include" -fi - -dnl Under Darwin we don't have support for -soname option and -dnl we need the -dynamiclib flag. Under Solaris, instead, we need -dnl the options -G -h. - -if test "$DARWIN" = yes; then - LDFLAGS="$LDFLAGS -dynamiclib" -elif test "$SUN" = yes; then - LDFLAGS="$LDFLAGS -G -h \$(LIBLOAD)" -else - LDFLAGS="$LDFLAGS -Wl,-soname,\$(LIBLOAD)" -fi - -dnl Check to see if in_addr_t is defined. -dnl Could use a specific configure test. - -AC_DEFUN(nxconf_INADDRT, -[AC_CACHE_CHECK(for in_addr_t, nxconf_cv_inaddrt, -[AC_TRY_COMPILE([#include ],[in_addr_t t; t = 1; return t;], -nxconf_cv_inaddrt=yes, nxconf_cv_inaddrt=no) -rm -f conftest*]) -INADDRT= -test "$nxconf_cv_inaddrt" = yes && INADDRT=yes]) -nxconf_INADDRT - -dnl If in_addr_t is not defined use unsigned int. - -if test "$INADDRT" != yes ; then - echo -e "using unsigned int for type in_addr_t" - CXXFLAGS="$CXXFLAGS -DIN_ADDR_T=unsigned" - CPPFLAGS="$CPPFLAGS -DIN_ADDR_T=unsigned" -else - CXXFLAGS="$CXXFLAGS -DIN_ADDR_T=in_addr_t" - CPPFLAGS="$CPPFLAGS -DIN_ADDR_T=in_addr_t" -fi - -dnl Check whether --with-version was given. - -AC_SUBST(LIBVERSION) -AC_SUBST(VERSION) -if test "${with_version}" = yes; then - VERSION=${ac_option} -else - VERSION=`cat VERSION` -fi -echo -e "compiling version ${VERSION}" - -LIBVERSION=`echo ${VERSION} | cut -d '.' -f 1` - -CXXFLAGS="$CXXFLAGS -DVERSION=\\\"${VERSION}\\\"" -CPPFLAGS="$CPPFLAGS -DVERSION=\\\"${VERSION}\\\"" - -dnl Finally compose the LIB variable. - -if test "$DARWIN" = yes ; then - LIBS="$LIBS $LIBSTATIC $LIBSHARED" -elif test "$SUN" = yes ; then - LIBS="$LIBS $LIBSTATIC $LIBSHARED" -else - LIBS="$LIBS $LIBSTATIC -shared $LIBSHARED" -fi - -dnl Check whether --with-symbols or --without-symbols was -dnl given and set the required optimization level. - -if test "${with_symbols}" = yes; then - echo -e "enabling production of debug symbols" - CXXFLAGS="-g $CXXFLAGS" - CPPFLAGS="-g $CPPFLAGS" -else - echo -e "disabling production of debug symbols" -fi - -dnl Check whether --with-info or --without-info was given. - -if test "${with_info}" = yes; then - echo -e "enabling info output in the log file" - CXXFLAGS="$CXXFLAGS -DINFO" - CPPFLAGS="$CPPFLAGS -DINFO" -else - echo -e "disabling info output in the log file" -fi - -dnl Check whether --with-valgrind or --without-valgrind was given. - -if test "${with_valgrind}" = yes; then - echo -e "enabling valgrind memory checker workarounds" - CXXFLAGS="$CXXFLAGS -DVALGRIND" - CPPFLAGS="$CPPFLAGS -DVALGRIND" -else - echo -e "disabling valgrind memory checker workarounds" -fi - -dnl Find makedepend somewhere. - -AC_SUBST(MAKEDEPEND) -MAKEDEPEND="$(which makedepend)" - -AC_OUTPUT(Makefile nxcompshad.pc) diff --git a/nxcompshad/include/Shadow.h b/nxcompshad/include/Shadow.h new file mode 100644 index 000000000..e1c57c432 --- /dev/null +++ b/nxcompshad/include/Shadow.h @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Shadow_H +#define Shadow_H + +#include + +#define NXShadowCorrectColor(length, buffer) \ +\ +{ \ + unsigned short a; \ + unsigned short b; \ + unsigned short *shorts; \ + int i; \ +\ + length >>= 1; \ + shorts = (unsigned short *)buffer; \ + for (i = 0; i < length ; i++) \ + { \ + a = shorts[i]; \ +\ + b = a & 63; \ + a <<= 1; \ + a = (a & ~127) | b; \ +\ + shorts[i] = a; \ + } \ +} + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char* UpdaterHandle; + +typedef struct _ShadowOptions +{ + char optionShmExtension; + char optionDamageExtension; + int optionShadowDisplayUid; +} ShadowOptions; + +extern ShadowOptions NXShadowOptions; + +extern int NXShadowCreate(void *, char *, char *, void **); +extern void NXShadowDestroy(void); + +/* + * Use an already opened Display connection. + * We use instead of to avoid + * useless dependences from Xlib headers. + */ + +extern int NXShadowAddUpdaterDisplay(void *display, int *width, int *height, + unsigned char *depth); +extern UpdaterHandle NXShadowAddUpdater(char *displayName); +extern int NXShadowRemoveUpdater(UpdaterHandle handle); +extern int NXShadowRemoveAllUpdaters(void); + +extern void NXShadowHandleInput(void); +extern int NXShadowHasChanged(int (*)(void *), void *, int *); +extern void NXShadowExportChanges(long *, char **); +extern int NXShadowHasUpdaters(void); +extern int NXShadowCaptureCursor(unsigned int wnd, void *vis); +extern void NXShadowColorCorrect(int, int, unsigned int, unsigned int, char *); +extern void NXShadowUpdateBuffer(void **); + +extern void NXShadowEvent(Display *, XEvent); +extern void NXShadowWebKeyEvent(KeySym keysym, Bool isKeyPress); + +extern void NXShadowSetDisplayUid(int uid); + +extern void NXShadowDisableShm(void); +extern void NXShadowDisableDamage(void); + +extern void NXShadowGetScreenSize(int *width, int *height); +extern void NXShadowSetScreenSize(int *width, int *height); + +extern void NXShadowInitKeymap(void *keysyms); + +#ifdef __cplusplus +} +#endif + +#endif /* Shadow_H */ + diff --git a/nxcompshad/install-sh b/nxcompshad/install-sh deleted file mode 100755 index 58719246f..000000000 --- a/nxcompshad/install-sh +++ /dev/null @@ -1,238 +0,0 @@ -#! /bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. -# - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/nxcompshad/m4/nx-macros.m4 b/nxcompshad/m4/nx-macros.m4 new file mode 120000 index 000000000..813e9b041 --- /dev/null +++ b/nxcompshad/m4/nx-macros.m4 @@ -0,0 +1 @@ +../../m4/nx-macros.m4 \ No newline at end of file diff --git a/nxcompshad/nxcompshad.pc.in b/nxcompshad/nxcompshad.pc.in index 80b75e3f5..b12ca3e12 100644 --- a/nxcompshad/nxcompshad.pc.in +++ b/nxcompshad/nxcompshad.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: nxcompshad Description: Shadow Session Support for NX Compression Library -Version: @VERSION@ +Version: @COMPSHAD_VERSION@ Requires: nxcomp Requires.private: x11 Cflags: -I${includedir} diff --git a/nxcompshad/src/Core.cpp b/nxcompshad/src/Core.cpp new file mode 100644 index 000000000..de5f9a897 --- /dev/null +++ b/nxcompshad/src/Core.cpp @@ -0,0 +1,626 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Core.h" +#include "Logger.h" + +const int CorePoller::maxSliceHeight_ = 20; +const int CorePoller::minSliceHeight_ = 3; + +const char CorePoller::interlace_[] = +{ + 0, 16, + 8, 24, + 4, 20, 12, 28, + 2, 18, 10, 26, 6, 22, 14, 30, + 1, 17, + 9, 25, + 5, 21, 13, 29, + 3, 19, 11, 27, 7, 23, 15, 31 +}; + +CorePoller::CorePoller(Input *input, Display *display) : input_(input) +{ + logTrace("CorePoller::CorePoller"); + + buffer_ = NULL; + lastUpdatedRegion_ = NULL; + lineStatus_ = NULL; + linePriority_ = NULL; + lefts_ = NULL; + rights_ = NULL; +} + +CorePoller::~CorePoller() +{ + logTrace("CorePoller::~CorePoller"); + + if (buffer_ != NULL) + { + delete [] buffer_; + + buffer_ = NULL; + } + + if (lastUpdatedRegion_ != NULL) + { + XDestroyRegion(lastUpdatedRegion_); + + lastUpdatedRegion_ = NULL; + } + + if (lineStatus_ != NULL) + { + delete [] lineStatus_; + + lineStatus_ = NULL; + } + + if (linePriority_ != NULL) + { + delete [] linePriority_; + + linePriority_ = NULL; + } + + if (lefts_ != NULL) + { + delete [] lefts_; + + lefts_ = NULL; + } + + if (rights_ != NULL) + { + delete [] rights_; + + rights_ = NULL; + } +} + +int CorePoller::init() +{ + logTrace("CorePoller::init"); + + createFrameBuffer(); + + if (buffer_ == NULL) + { + logError("CorePoller::init", ESET(ENOMEM)); + + return -1; + } + + logTest("CorePoller::init", "Allocated frame buffer at [%p] for [%d] bytes.", + buffer_, bpl_ * height_); + + if (lastUpdatedRegion_ != NULL) + { + XDestroyRegion(lastUpdatedRegion_); + + lastUpdatedRegion_ = NULL; + } + + lastUpdatedRegion_ = XCreateRegion(); + + if (lineStatus_ != NULL) + { + delete[] lineStatus_; + } + + lineStatus_ = new LineStatus[height_ + 1]; + + if (lineStatus_ == NULL) + { + logError("CorePoller::init", ESET(ENOMEM)); + + return -1; + } + + // + // We need this boundary element to + // speed up the algo. + // + + if (linePriority_ != NULL) + { + delete[] linePriority_; + } + + linePriority_ = new int [height_ + 1]; + + if (linePriority_ == NULL) + { + logError("CorePoller::init", ESET(ENOMEM)); + + return -1; + } + + for (unsigned int i = 0; i < height_; i++) + { + linePriority_[i] = HIGHEST_PRIORITY; + } + + if (lefts_ != NULL) + { + delete[] lefts_; + } + + lefts_ = new int [height_]; + + if (rights_ != NULL) + { + delete[] rights_; + } + + rights_ = new int [height_]; + + for (unsigned int i = 0; i < height_; i++) + { + rights_[i] = lefts_[i] = 0; + } + + return 1; +} + +int CorePoller::isChanged(int (*checkIfInputCallback)(void *), void *arg, int *suspended) +{ + logTrace("CorePoller::isChanged"); + +#if defined(__CYGWIN32__) || defined(WIN32) + + checkDesktop(); + +#endif + +#if !defined(__CYGWIN32__) && !defined(WIN32) + + if (mirror_ == 1) + { + int result = mirrorChanges_; + + mirrorChanges_ = 0; + + return result; + } + +#endif + + logDebug("CorePoller:isChanged", "Going to use default polling algorithm.\n"); + + // + // In order to allow this function to + // be suspended and resumed later, we + // need to save these two status vars. + // + + static int idxIlace = 0; + static int curLine = 0; + + + const long timeout = 50; + long oldTime; + long newTime; + struct timeval ts; + + gettimeofday(&ts, NULL); + + oldTime = ts.tv_sec * 1000 + ts.tv_usec / 1000; + + if (curLine == 0) // && idxIlace == 0 ? + { + for (unsigned int i = 0; i < height_; i++) + { + lineStatus_[i] = LINE_NOT_CHECKED; + } + } + + int foundChanges = 0; + + foundChanges = 0; + + int curIlace = interlace_[idxIlace]; + + bool moveBackward = false; + + logDebug("CorePoller::isChanged", "Interlace index [%d] interlace [%d].", idxIlace, curIlace); + + for (; curLine < (int) height_; curLine++) + { + logDebug("CorePoller::isChanged", "Analizing line [%d] move backward [%d] status [%d] priority [%d].", + curLine, moveBackward, lineStatus_[curIlace], linePriority_[curLine]); + + // + // Ask the caller if the polling have to be suspended. + // + + if ((*checkIfInputCallback)(arg) == 1) + { + *suspended = 1; + + break; + } + + // + // Suspend if too much time is elapsed. + // + + gettimeofday(&ts, NULL); + + newTime = ts.tv_sec * 1000 + ts.tv_usec / 1000; + + if (newTime - oldTime >= timeout) + { + *suspended = 1; + + break; + } + + oldTime = newTime; + + if (lineStatus_[curLine] != LINE_NOT_CHECKED) + { + continue; + } + + if (moveBackward) + { + moveBackward = false; + } + else + { + switch (linePriority_[curLine]) + { + case 1: + case 29: + { + // + // It was a priority, + // but now it may not be. + // + } + case 31: + { + // + // Not a priority, still isn't. + // + + linePriority_[curLine] = NOT_PRIORITY; + + break; + } + case 0: + { + // + // Make it a priority. + // + + linePriority_[curLine] = PRIORITY; + + break; + } + default: + { + linePriority_[curLine]--; + + break; + } + } + + if ((linePriority_[curLine] > PRIORITY) && ((curLine & 31) != curIlace)) + { + continue; + } + } + + XRectangle rect = {0, curLine, width_, 1}; + + char *buffer; + + logDebug("CorePoller::isChanged", "Checking line [%d].", curLine); + + if ((buffer = getRect(rect)) == NULL) + { + logDebug("CorePoller::isChanged", "Failed to retrieve line [%d].", curLine); + + return -1; + } + + if (memcmp(buffer, buffer_ + curLine * bpl_, bpl_) == 0 || differ(buffer, rect) == 0) + { + logDebug("CorePoller::isChanged", "Data buffer didn't change."); + + lineStatus_[curLine] = LINE_NOT_CHANGED; + + continue; + } + + rect.x = lefts_[rect.y]; + rect.width = rights_[rect.y] - lefts_[rect.y] + 1; + + update(buffer + rect.x * bpp_, rect); + + foundChanges = 1; + + lineStatus_[curLine] = LINE_HAS_CHANGED; + + // + // Wake up the next line. + // + + if (linePriority_[curLine + 1] > PRIORITY) + { + linePriority_[curLine + 1] = HIGHEST_PRIORITY; + } + + // + // Give this line priority. + // + + linePriority_[curLine] = HIGHEST_PRIORITY; + + // + // Wake up previous line. + // + + if (curLine > 0 && lineStatus_[curLine - 1] == LINE_NOT_CHECKED) + { + moveBackward = true; + curLine -= 2; + } + } + + // + // Execution reached the end of loop. + // + + if (curLine == (int) height_) + { + idxIlace = (idxIlace + 1) % 32; + + curLine = 0; + } + + // + // Create the region of changed pixels. + // + + if (foundChanges) + { + int start, last, curLine, left, right; + + for (curLine = 0; curLine < (int) height_; curLine++) + { + if (lineStatus_[curLine] == LINE_HAS_CHANGED) + { + break; + } + } + + start = curLine; + last = curLine; + + left = lefts_[curLine]; + right = rights_[curLine]; + curLine++; + + while (1) + { + for (; curLine < (int) height_; curLine++) + { + if (lineStatus_[curLine] == LINE_HAS_CHANGED) + { + break; + } + } + + if (curLine == (int) height_) + { + break; + } + + if ((curLine - last > minSliceHeight_) || (last - start > maxSliceHeight_)) + { + XRectangle rect = {left, start, right - left + 1, last - start + 1}; + + XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_); + + start = curLine; + left = lefts_[curLine]; + right = rights_[curLine]; + } + else + { + if (lefts_[curLine] < left) + { + left = lefts_[curLine]; + } + + if (rights_[curLine] > right) + { + right = rights_[curLine]; + } + } + + last = curLine; + + curLine++; + } + + // + // Send last block. + // + + if (last >= start) + { + XRectangle rect = {left, start, right - left + 1, last - start + 1}; + + XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_); + } + } + + return foundChanges; +} + +int CorePoller::differ(char *buffer, XRectangle r) +{ + logTrace("CorePoller::differ"); + + int bpl = bpp_ * r.width; + int i; + char *pBuf; + char *pFb; + + pBuf = (buffer); + pFb = (buffer_ + r.x + r.y * bpl_); + + for (i = 0; i < bpl; i++) + { + if (*pFb++ != *pBuf++) + { + lefts_[r.y] = i / bpp_; + + break; + } + } + + if (i == bpl) + { + return 0; + } + + pBuf = (buffer) + bpl - 1; + pFb = (buffer_ + r.x + r.y * bpl_) + bpl - 1; + + int j = i - 1; + + for (i = bpl - 1; i > j; i--) + { + if (*pFb-- != *pBuf--) + { + rights_[r.y] = i / bpp_; + + break; + } + } + + return 1; +} + +void CorePoller::update(char *src, XRectangle r) +{ + logTrace("CorePoller::update"); + + char *dst = buffer_ + r.x * bpp_ + r.y * bpl_; + int bpl = bpp_ * r.width; + + for (unsigned int i = 0; i < r.height; i++) + { + if(((r.x * bpp_ + r.y * bpl_) + bpl) > (bpl_ * height_)) + { + // + // Out of bounds. Maybe a resize is going on. + // + + continue; + } + + memcpy(dst, src, bpl); + + src += bpl; + + dst += bpl_; + } +} + +void CorePoller::handleEvent(Display *display, XEvent *event) +{ + logTrace("CorePoller::handleEvent"); + + switch (event -> type) + { + case KeyPress: + case KeyRelease: + { + handleKeyboardEvent(display, event); + break; + } + case ButtonPress: + case ButtonRelease: + case MotionNotify: + { + handleMouseEvent(display, event); + break; + } + default: + { + logTest("CorePoller::handleEvent", "Handling unexpected event [%d] from display [%p].", + event -> type, display); + break; + } + } +} + +void CorePoller::handleWebKeyEvent(KeySym keysym, Bool isKeyPress) +{ + logTrace("CorePoller::handleWebKeyEvent"); + + handleWebKeyboardEvent(keysym, isKeyPress); +} + +void CorePoller::handleInput() +{ + while (input_ -> checkIfEvent()) + { + Display *display = input_ -> currentDisplay(); + XEvent *event = input_ -> popEvent(); + + handleEvent(display, event); + + delete event; + } +} + +void CorePoller::createFrameBuffer() +{ + logTrace("CorePoller::createFrameBuffer"); + + if (buffer_ == NULL) + { + buffer_ = new char[bpl_ * height_]; + } +} diff --git a/nxcompshad/src/Core.h b/nxcompshad/src/Core.h new file mode 100644 index 000000000..91f3f1e22 --- /dev/null +++ b/nxcompshad/src/Core.h @@ -0,0 +1,212 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef CorePoller_H +#define CorePoller_H + +#include + +#include "Logger.h" +#include "Regions.h" +#include "Input.h" + +typedef enum{ + LINE_HAS_CHANGED, + LINE_NOT_CHECKED, + LINE_NOT_CHANGED +} LineStatus; + +typedef enum{ + HIGHEST_PRIORITY = 0, + PRIORITY = 30, + NOT_PRIORITY = 90 +} LinePriority; + +class CorePoller +{ + public: + + CorePoller(Input*, Display*); + + virtual ~CorePoller(); + + virtual int init(); + + unsigned int width() const; + + unsigned int height() const; + + unsigned char depth() const; + + int isChanged(int (*)(void*), void *, int *); + + char *getFrameBuffer() const; + + void destroyFrameBuffer(); + + void createFrameBuffer(); + + Region lastUpdatedRegion(); + + Region getLastUpdatedRegion(); + + void handleInput(); + + void handleEvent(Display *, XEvent *); + + void handleWebKeyEvent(KeySym keysym, Bool isKeyPress); + + Display *getShadowDisplay(); + + void setShadowDisplay(Display *shadowDisplay); + + protected: + + unsigned int bpp_; + + unsigned int bpl_; + + unsigned int width_; + + unsigned int height_; + + int depth_; + + char *buffer_; + + unsigned long redMask_; + unsigned long greenMask_; + unsigned long blueMask_; + unsigned long colorMask_[3]; + + char mirror_; + + char mirrorChanges_; + + virtual int updateShadowFrameBuffer(void) = 0; + + virtual char *getRect(XRectangle r) = 0; + + int imageByteOrder_; + + #ifdef __CYGWIN32__ + virtual char checkDesktop(void) = 0; + #endif + + Display *shadowDisplay_; + + void update(char *src, XRectangle r); + + Region lastUpdatedRegion_; + + private: + + virtual void handleKeyboardEvent(Display *, XEvent *) = 0; + + virtual void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) = 0; + + virtual void handleMouseEvent(Display *, XEvent *) = 0; + + Input *input_; + + static const int maxSliceHeight_; + static const int minSliceHeight_; + + LineStatus *lineStatus_; + int *linePriority_; + + static const char interlace_[]; + + int *lefts_; + int *rights_; + + // FIXME: Make them friend. + + int differ(char *src, XRectangle r); +}; + +inline unsigned int CorePoller::width() const +{ + return width_; +} + +inline unsigned int CorePoller::height() const +{ + return height_; +} + +inline unsigned char CorePoller::depth() const +{ + return depth_; +} + +inline char *CorePoller::getFrameBuffer() const +{ + return buffer_; +} + +inline void CorePoller::destroyFrameBuffer() +{ + if (buffer_ != NULL) + { + delete[] buffer_; + buffer_ = NULL; + } +} + +inline Region CorePoller::lastUpdatedRegion() +{ + Region region = lastUpdatedRegion_; + + lastUpdatedRegion_ = XCreateRegion(); + + if (lastUpdatedRegion_ == NULL) + { + logError("CorePoller::lastUpdatedRegion", ESET(ENOMEM)); + + lastUpdatedRegion_ = region; + + return NULL; + } + + return region; +} + +inline Region CorePoller::getLastUpdatedRegion() +{ + return lastUpdatedRegion_; +} + +inline Display *CorePoller::getShadowDisplay() +{ + return shadowDisplay_ ; +} + +inline void CorePoller::setShadowDisplay(Display *shadowDisplay) +{ + shadowDisplay_ = shadowDisplay; +} + +#endif /* CorePoller_H */ diff --git a/nxcompshad/src/Input.cpp b/nxcompshad/src/Input.cpp new file mode 100644 index 000000000..8de74c3c3 --- /dev/null +++ b/nxcompshad/src/Input.cpp @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Input.h" +#include "Logger.h" + +Input::Input() +{ + logTrace("Input::Input"); + + eventsHead_ = NULL; + eventsTail_ = NULL; + keymap_ = NULL; +} + +Input::~Input() +{ + logTrace("Input::~Input"); + + Event *head = eventsHead_; + + while (head) + { + Event *next = head -> next; + + delete head -> event; + delete head; + + head = next; + } + + if (keymap_ != NULL) + { + logDebug("Input::~Input", "Delete keymap_ [%p].", keymap_); + + delete [] keymap_; + } +} + +void Input::pushEvent(Display *display, XEvent *event) +{ + Event *tail = new Event; + + if (tail == NULL) + { + logError("Input::pushEvent", ESET(ENOMEM)); + + return; + } + + tail -> next = NULL; + tail -> display = display; + tail -> event = event; + + if (eventsHead_ == NULL) + { + eventsHead_ = tail; + } + else + { + eventsTail_ -> next = tail; + } + + eventsTail_ = tail; +} + +XEvent *Input::popEvent() +{ + Event *head = eventsHead_; + + if (head == NULL) + { + return 0; + } + + XEvent *event = head -> event; + + eventsHead_ = head -> next; + + delete head; + + if (eventsHead_ == NULL) + { + eventsTail_ = NULL; + } + + return event; +} + +int Input::removeAllEvents(Display *display) +{ + logTrace("Input::removeAllEvents"); + + int nRemoved = 0; + + Event *current = eventsHead_; + + while (current) + { + if (display == current -> display) + { + // + // Update head of list. + // + + if (current == eventsHead_) + { + eventsHead_ = current -> next; + } + + // + // Update tail of list. + // + + if (current == eventsTail_) + { + eventsTail_ = eventsHead_; + + while (eventsTail_ && eventsTail_ -> next) + { + eventsTail_ = eventsTail_ -> next; + } + } + + // + // Remove event. + // + + Event *next = current -> next; + + delete current -> event; + delete current; + + current = next; + + nRemoved++; + } + else + { + current = current -> next; + } + } + + return nRemoved; +} + diff --git a/nxcompshad/src/Input.h b/nxcompshad/src/Input.h new file mode 100644 index 000000000..cbba029a9 --- /dev/null +++ b/nxcompshad/src/Input.h @@ -0,0 +1,99 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Input_H +#define Input_H + +#include + +typedef struct Event +{ + struct Event *next; + Display *display; + XEvent *event; +} Event; + +class Input +{ + public: + + Input(); + + ~Input(); + + int checkIfEvent(); + + void pushEvent(Display *, XEvent *); + + XEvent *popEvent(); + Display *currentDisplay(); + + int removeAllEvents(Display *); + + void setKeymap(char *keymap); + char *getKeymap(); + + void setShadowDisplayName(char *shadowDisplayName); + char *getShadowDisplayName(); + + private: + + Event *eventsHead_; + Event *eventsTail_; + char *keymap_; + char *shadowDisplayName_; +}; + +inline Display *Input::currentDisplay() +{ + return eventsHead_ ? eventsHead_ -> display : NULL; +} + +inline int Input::checkIfEvent() +{ + return (eventsHead_ != NULL); +} + +inline void Input::setKeymap(char *keymap) +{ + keymap_ = keymap; +} + +inline char *Input::getKeymap() +{ + return keymap_; +} + +inline void Input::setShadowDisplayName(char *shadowDisplayName) +{ + shadowDisplayName_ = shadowDisplayName; +} + +inline char *Input::getShadowDisplayName() +{ + return shadowDisplayName_; +} + +#endif /* Input_H */ diff --git a/nxcompshad/src/Logger.cpp b/nxcompshad/src/Logger.cpp new file mode 100644 index 000000000..9648509b8 --- /dev/null +++ b/nxcompshad/src/Logger.cpp @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#define DEBUG + +#include "Misc.h" +#include "Logger.h" + +Logger logger; + +void Logger::user(const char *format, va_list arguments) +{ + char string[1024]; + + vsnprintf(string, 1024, format, arguments); + + fprintf(stderr, "%s\n", string); +} + +void Logger::error(const char *name, int error) +{ + fprintf(stderr, "PANIC! %s: Failed with code %d: %s\n", + name, error, strerror(error)); +} + +void Logger::warning(const char *name, const char *format, va_list arguments) +{ + char string[1024]; + + vsnprintf(string, 1024, format, arguments); + + fprintf(stderr, "%s: WARNING! %s\n", name, string); +} + +void Logger::test(const char *name, const char *format, va_list arguments) +{ + char string[1024]; + + vsnprintf(string, 1024, format, arguments); + + fprintf(stderr, "%s: %s\n", name, string); +} + +void Logger::trace(const char *name) +{ + fprintf(stderr, "%s\n", name); +} + +void Logger::debug(const char *name, const char *format, va_list arguments) +{ + char string[1024]; + + vsnprintf(string, 1024, format, arguments); + + fprintf(stderr, "%s: %s\n", name, string); +} + +void Logger::dump(const char *name, const char *data, int size) +{ + fprintf(stderr, "%s: Dumping %d bytes of data at %p\n", + name, size, data); + + for (int i = 0; i < size;) + { + fprintf(stderr, "[%d]\t", i); + + int t = i; + + for (unsigned int ii = 0; i < size && ii < 8; i++, ii++) + { + fprintf(stderr, "%02x/%d\t", data[i] & 0xff, data[i]); + } + + for (unsigned int ii = i % 8; ii > 0 && ii < 8; ii++) + { + fprintf(stderr, "\t"); + } + + i = t; + + for (unsigned int ii = 0; i < size && ii < 8; i++, ii++) + { + if (isprint(data[i])) + { + fprintf(stderr, "%c", data[i]); + } + else + { + fprintf(stderr, "."); + } + } + + fprintf(stderr, "\n"); + } +} diff --git a/nxcompshad/src/Logger.h b/nxcompshad/src/Logger.h new file mode 100644 index 000000000..eba81f642 --- /dev/null +++ b/nxcompshad/src/Logger.h @@ -0,0 +1,167 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Logger_H +#define Logger_H + +#include +#include + +// +// Error handling macros. +// + +#define ESET(e) (errno = (e)) +#define EGET() (errno) +#define ESTR() strerror(errno) + +extern class Logger logger; + +class Logger +{ + public: + + void user(const char *format, va_list arguments); + + void error(const char *name, int error); + + void warning(const char *name, const char *format, va_list arguments); + + void test(const char *name, const char *format, va_list arguments); + + void trace(const char *name); + + void debug(const char *name, const char *format, va_list arguments); + + void dump(const char *name, const char *data, int size); +}; + +static inline void logUser(const char *format, ...) \ + __attribute__((format(printf, 1, 2))) __attribute__((__unused__)); + +static inline void logError(const char *name, int error) \ + __attribute__((__unused__)); + +static inline void logWarning(const char *name, const char *format, ...) \ + __attribute__((__unused__)); + +static inline void logTest(const char *name, const char *format, ...) \ + __attribute__((format(printf, 2, 3))) __attribute__((__unused__)); + +static inline void logTrace(const char *name) \ + __attribute__((__unused__)); + +static inline void logDebug(const char *name, const char *format, ...) \ + __attribute__((format(printf, 2, 3))) __attribute__((__unused__)); + +static inline void logDump(const char *name, const char *data, int size) \ + __attribute__((__unused__)); + +static inline void logUser(const char *format, ...) +{ + va_list arguments; + + va_start(arguments, format); + + logger.user(format, arguments); + + va_end(arguments); +} + +static inline void logError(const char *name, int error) +{ + #if defined(DEBUG) || defined(TEST) || \ + defined(WARNING) || defined(PANIC) + + logger.error(name, error); + + #endif +} + +static inline void logWarning(const char *name, const char *format, ...) +{ + #if defined(DEBUG) || defined(TEST) || \ + defined(WARNING) + + va_list arguments; + + va_start(arguments, format); + + logger.warning(name, format, arguments); + + va_end(arguments); + + #endif +} + +static inline void logTest(const char *name, const char *format, ...) +{ + #if defined(TEST) + + va_list arguments; + + va_start(arguments, format); + + logger.test(name, format, arguments); + + va_end(arguments); + + #endif +} + +static inline void logTrace(const char *name) +{ + #if defined(DEBUG) + + logger.trace(name); + + #endif +} + +static inline void logDebug(const char *name, const char *format, ...) +{ + #if defined(DEBUG) + + va_list arguments; + + va_start(arguments, format); + + logger.debug(name, format, arguments); + + va_end(arguments); + + #endif +} + +static inline void logDump(const char *name, const char *data, int size) +{ + #if defined(TEST) + + logger.dump(name, data, size); + + #endif +} + +#endif /* Logger_H */ diff --git a/nxcompshad/src/Makefile.am b/nxcompshad/src/Makefile.am new file mode 100644 index 000000000..c7f45ba27 --- /dev/null +++ b/nxcompshad/src/Makefile.am @@ -0,0 +1,45 @@ +NULL = + +lib_LTLIBRARIES = libXcompshad.la + +libXcompshad_la_SOURCES = \ + Core.cpp \ + Input.cpp \ + Logger.cpp \ + Manager.cpp \ + Shadow.cpp \ + Updater.cpp \ + Win.cpp \ + X11.cpp \ + $(NULL) + +libXcompshad_la_LIBADD = \ + @Xext_LIBS@ \ + @Xdamage_LIBS@ \ + @Xrandr_LIBS@ \ + @Xtst_LIBS@ \ + -L$(top_srcdir)/../nx-X11/exports/lib -lNX_X11 \ + $(NULL) + +AM_CFLAGS = \ + $(Xext_CFLAGS) \ + $(Xdamage_CFLAGS) \ + $(Xrandr_CFLAGS) \ + $(Xtst_CFLAGS) \ + $(NULL) + +AM_CXXFLAGS = \ + $(BASE_CXXFLAGS) \ + $(NULL) + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/../nx-X11/exports/include \ + $(NULL) + +libXcompshad_la_LDFLAGS = -version-number @LT_COMPSHAD_VERSION@ -no-undefined + +libXcompshadincludedir = $(includedir)/nx +libXcompshadinclude_HEADERS = \ + $(top_srcdir)/include/Shadow.h \ + $(NULL) diff --git a/nxcompshad/src/Manager.cpp b/nxcompshad/src/Manager.cpp new file mode 100644 index 000000000..6e3f6b1b0 --- /dev/null +++ b/nxcompshad/src/Manager.cpp @@ -0,0 +1,264 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Manager.h" +#include "Logger.h" + +UpdateManager::UpdateManager(int w, int h, char *f, Input *i) + : width_(w), height_(h), frameBuffer_(f), input_(i) +{ + logTrace("UpdateManager::UpdateManager"); + + nUpdater = 0; + updaterVector = NULL; + updateManagerRegion_ = NULL; +} + +UpdateManager::~UpdateManager() +{ + logTrace("UpdateManager::~UpdateManager"); + + for (int i = 0; i < nUpdater; i++) + { + delete updaterVector[i]; + } + + delete [] updaterVector; +} + +Updater *UpdateManager::createUpdater(char *displayName, Display *display) +{ + Updater *updater = new Updater(displayName, display); + + if (updater == NULL) + { + logError("UpdateManager::createUpdater", ESET(ENOMEM)); + + return NULL; + } + + if (updater -> init(width_, height_, frameBuffer_, input_) == -1) + { + logError("UpdateManager::createUpdater", EGET()); + + delete updater; + + return NULL; + } + + return updater; +} + +UpdaterHandle UpdateManager::addUpdater(char *displayName, Display *display) +{ + Updater *newUpdater = createUpdater(displayName, display); + + if (newUpdater == NULL) + { + logError("UpdateManager::addUpdater", EGET()); + + return NULL; + } + + Updater **newUpdaterVector = new Updater*[nUpdater + 1]; + + if (newUpdaterVector == NULL) + { + logError("UpdateManager::addUpdater", ESET(ENOMEM)); + + delete newUpdater; + + return NULL; + } + + for (int i = 0; i < nUpdater; i++) + { + newUpdaterVector[i] = updaterVector[i]; + } + + newUpdaterVector[nUpdater] = newUpdater; + + delete [] updaterVector; + + updaterVector = newUpdaterVector; + + nUpdater++; + + logTest("UpdateManager::AddUpdater", "Number of updaters [%d].", nUpdater); + + return reinterpret_cast(newUpdater); +} + +int UpdateManager::removeAllUpdaters() +{ + logTest("UpdateManager::removeAllUpdaters", "Number of updaters [%d].", nUpdater); + + int nullUpdaters = 0; + + for (int i = nUpdater; i > 0; i--) + { + if (removeUpdater(reinterpret_cast(updaterVector[i - 1])) == 0) + { + nullUpdaters++; + } + } + + if (nUpdater == 0) + { + return 1; + } + + if (nUpdater == nullUpdaters) + { + logTest("UpdateManager::removeAllUpdaters", "Ignored null records in Updater vector."); + + return 0; + } + + logTest("UpdateManager::removeAllUpdaters", "Failed to remove some updaters."); + + return -1; +} + +int UpdateManager::removeUpdater(UpdaterHandle handle) +{ + Updater * const updater = (Updater*) handle; + + logTest("UpdateManager::removeUpdater", "Removing Updater [%p].", updater); + + if (updater == NULL) + { + return 0; + } + + for (int i = 0; i < nUpdater; i++) + { + if (updater == updaterVector[i]) + { + updaterVector[i] = updaterVector[nUpdater - 1]; + + nUpdater--; + + delete updater; + + return 1; + } + } + + logTest("UpdateManager::removeUpdater", "Couldn't find Updater [%p].", updater); + + return -1; +} + +void UpdateManager::addRegion(Region region) +{ + logTrace("UpdateManager::addRegion"); + + for (int i = 0; i < nUpdater; i++) + { + updaterVector[i] -> addRegion(region); + } + + XDestroyRegion(region); +} + +void UpdateManager::update() +{ + logTrace("UpdateManager::update"); + + for (int i = 0; i < nUpdater; i++) + { + /*updaterVector[i] -> update();*/ + if (updaterVector[i] -> getUpdateRegion()) + { + logDebug("UpdateManager::update", "pRegion [%p] rect[%ld].", + updaterVector[i] -> getUpdateRegion(), (updaterVector[i] -> getUpdateRegion()) -> numRects); + + updateManagerRegion_ = updaterVector[i] -> getUpdateRegion(); + // + // FIXME: Remove me. + // + for (int j = 0; j < updateManagerRegion_ -> numRects; j++) + { + int x = updateManagerRegion_ -> rects[j].x1; + int y = updateManagerRegion_ -> rects[j].y1; + unsigned int width = updateManagerRegion_ -> rects[j].x2 - updateManagerRegion_ -> rects[j].x1; + unsigned int height = updateManagerRegion_ -> rects[j].y2 - updateManagerRegion_ -> rects[j].y1; + logDebug("UpdateManager::update", "x[%d]y[%d]width[%u]height[%u], updateManagerRegion_[%p]", + x, y, width, height, updateManagerRegion_); + } + } + } +} + +void UpdateManager::handleInput() +{ + logTrace("UpdateManager::handleInput"); + + for (int i = 0; i < nUpdater; i++) + { + try + { + updaterVector[i] -> handleInput(); + } + catch (UpdaterClosing u) + { + logTest("UpdateManager::handleInput", "Catched exception UpdaterClosing()."); + + removeUpdater((UpdaterHandle)updaterVector[i]); + + // + // Now the i-element of the updaterVector + // is changed. We don't want to skip it. + // + + i--; + } + } +} + +void UpdateManager::newRegion() +{ + logTrace("UpdateManager::newRegion"); + + for (int i = 0; i < nUpdater; i++) + { + updaterVector[i] -> newRegion(); + } +} diff --git a/nxcompshad/src/Manager.h b/nxcompshad/src/Manager.h new file mode 100644 index 000000000..92a82cd32 --- /dev/null +++ b/nxcompshad/src/Manager.h @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef UpdateManager_H +#define UpdateManager_H + +#include + +#include "Updater.h" +#include "Regions.h" +#include "Input.h" + +typedef char* UpdaterHandle; + +class UpdateManager +{ + public: + + UpdateManager(int, int, char *, Input *); + + ~UpdateManager(); + + void handleInput(); + + void addRegion(Region); + + void update(); + + UpdaterHandle addUpdater(char *displayName, Display *display); + + int removeUpdater(UpdaterHandle); + + int removeAllUpdaters(); + + int numberOfUpdaters(); + + int getWidth(); + + int getHeight(); + + char *getBuffer(); + + Region getUpdateManagerRegion(); + + void destroyUpdateManagerRegion(); + + void newRegion(); + + private: + + Updater *createUpdater(char *displayName, Display *display); + + int width_; + int height_; + char *frameBuffer_; + Input *input_; + + int nUpdater; + + Updater **updaterVector; + + Region updateManagerRegion_; + +}; + +inline int UpdateManager::numberOfUpdaters() +{ + return nUpdater; +} + +inline int UpdateManager::getWidth() +{ + return width_; +} + +inline int UpdateManager::getHeight() +{ + return height_; +} + +inline char *UpdateManager::getBuffer() +{ + return frameBuffer_; +} + +inline Region UpdateManager::getUpdateManagerRegion() +{ + return updateManagerRegion_; +} + +inline void UpdateManager::destroyUpdateManagerRegion() +{ + if (updateManagerRegion_ != NULL) + { + XDestroyRegion(updateManagerRegion_); + + updateManagerRegion_ = NULL; + } +} + +#endif /* UpdateManager_H */ diff --git a/nxcompshad/src/Misc.h b/nxcompshad/src/Misc.h new file mode 100644 index 000000000..9386dc080 --- /dev/null +++ b/nxcompshad/src/Misc.h @@ -0,0 +1,50 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Misc_H +#define Misc_H + +#include + +#include +#include + +using namespace std; + +// +// Error handling macros. +// + +#define ESET(e) (errno = (e)) +#define EGET() (errno) +#define ESTR() strerror(errno) + +// +// Log file. +// + +extern ostream *logofs; + +#endif /* Misc_H */ diff --git a/nxcompshad/src/Poller.h b/nxcompshad/src/Poller.h new file mode 100644 index 000000000..6236f872f --- /dev/null +++ b/nxcompshad/src/Poller.h @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Poller_H +#define Poller_H + +#if defined(__CYGWIN32__) || defined(WIN32) + +#include "Win.h" + +#else + +#include "X11.h" + +#endif + +#endif /* Poller_H */ diff --git a/nxcompshad/src/Regions.h b/nxcompshad/src/Regions.h new file mode 100644 index 000000000..59fdcb46c --- /dev/null +++ b/nxcompshad/src/Regions.h @@ -0,0 +1,43 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Region_H +#define Region_H + +#include +#include + +typedef struct { + short x1, x2, y1, y2; +} Box, BOX, BoxRec, *BoxPtr; + +typedef struct _XRegion { + long size; + long numRects; + BOX *rects; + BOX extents; +}; + +#endif /* Region_H */ diff --git a/nxcompshad/src/Shadow.cpp b/nxcompshad/src/Shadow.cpp new file mode 100644 index 000000000..3db5039ce --- /dev/null +++ b/nxcompshad/src/Shadow.cpp @@ -0,0 +1,482 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Logger.h" +#include "Shadow.h" +#include "Poller.h" +#include "Manager.h" + +typedef struct { + KeySym *map; + KeyCode minKeyCode, + maxKeyCode; + int mapWidth; +} KeySymsRec, *KeySymsPtr; + +KeySymsPtr NXShadowKeymap = NULL; + +ShadowOptions NXShadowOptions = {1, 1, -1}; + +static int mirrorException = 0; + +static UpdateManager *updateManager; +static Poller *poller; +static Input *input; + +int NXShadowRemoveAllUpdaters(); + +inline bool NXShadowNotInitialized() +{ + // + // updateManager depends on input and poller. + // So this test seem redundant. + // + // return (input == NULL) || (poller == NULL) || (updateManager == NULL); + // + + return (updateManager == NULL); +} + +#ifdef NEED_SIGNAL_HANDLER +static void NXSignalHandler(int signal) +{ + logTest("NXSignalHandler", "Got signal [%d]", signal); + + if (signal == SIGINT) + { + mirrorException = 1; + } + else if (signal == SIGTERM) + { + mirrorException = 1; + } +} + +static int NXInitSignal() +{ + logTrace("NXInitSignal"); + + struct sigaction sa; + + sa.sa_handler = NXSignalHandler; + sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + + int res; + + while ((res = sigaction(SIGINT, &sa, NULL)) == -1 && + errno == EINTR); + + if (res == -1) + { + logError("NXInitSignal", EGET()); + + return -1; + } + + return 1; +} +#endif + +static void NXHandleException() +{ + if (mirrorException) + { + mirrorException = 0; + + NXShadowRemoveAllUpdaters(); + } +} + +static int NXCreateInput(char *keymap, char *shadowDisplayName) +{ + logTrace("NXCreateInput"); + + input = new Input; + + if (input == NULL) + { + logError("NXCreateInput", ESET(ENOMEM)); + + return -1; + } + + input -> setKeymap(keymap); + + input -> setShadowDisplayName(shadowDisplayName); + + return 1; +} + +static int NXCreatePoller(Display *display, Display **shadowDisplay) +{ + logTrace("NXCreatePoller"); + + if (input == NULL) + { + logError("NXCreatePoller", ESET(EBADF)); + + return -1; + } + + poller = new Poller(input,display); + + if (poller == NULL) + { + logError("NXCreatePoller", ESET(ENOMEM)); + + return -1; + } + + if (poller -> init() == -1) + { + logWarning("NXCreatePoller", "Failed to initialize poller."); + + return -1; + } + + *shadowDisplay = poller -> getShadowDisplay(); + + logTest("NXCreatePoller", "Poller geometry [%d, %d], ShadowDisplay[%p].", poller -> width(), + poller -> height(), (Display *) *shadowDisplay); + + return 1; +} + +static int NXCreateUpdateManager() +{ + logTrace("NXCreateUpdateManager"); + + if (input == NULL || poller == NULL) + { + logError("NXCreateUpdateManager", ESET(EBADF)); + + return -1; + } + + updateManager = new UpdateManager(poller -> width(), poller -> height(), + poller -> getFrameBuffer(), input); + + if (updateManager == NULL) + { + logError("NXCreateUpdateManager", ESET(ENOMEM)); + + return -1; + } + + return 1; +} + +void NXShadowResetOptions() +{ + NXShadowOptions.optionShmExtension = 1; + NXShadowOptions.optionDamageExtension = 1; +} + +// +// Exported functions. +// + +int NXShadowHasUpdaters() +{ + logTrace("NXShadowHasUpdaters"); + + return (updateManager && updateManager -> numberOfUpdaters()) ? 1 : 0; +} + +int NXShadowRemoveAllUpdaters() +{ + logTrace("NXShadowRemoveAllUpdaters"); + + return updateManager ? updateManager -> removeAllUpdaters() : 0; +} + +int NXShadowRemoveUpdater(UpdaterHandle handle) +{ + logTrace("NXShadowRemoveUpdater"); + + return updateManager ? updateManager -> removeUpdater(handle) : 0; +} + +UpdaterHandle NXShadowAddUpdater(char *displayName) +{ + logTrace("NXShadowAddUpdater"); + + return updateManager ? updateManager -> addUpdater(displayName, NULL) : NULL; +} + +int NXShadowAddUpdaterDisplay(void *dpy, int *w, int *h, unsigned char *d) +{ + Display *display = reinterpret_cast(dpy); + + logTrace("NXShadowAddUpdaterDisplay"); + + if ((updateManager ? updateManager -> addUpdater(NULL, display) : NULL) == NULL) + { + logTest("NXShadowAddUpdaterDisplay", "Error"); + + return 0; + } + + *w = updateManager -> getWidth(); + *h = updateManager -> getHeight(); + *d = poller -> depth(); + + return 1; +} + +int NXShadowCreate(void *dpy, char *keymap, char* shadowDisplayName, void **shadowDpy) +{ + logTrace("NXShadowCreate"); + + Display *display = reinterpret_cast(dpy); + Display **shadowDisplay = reinterpret_cast(shadowDpy); + +/* if (NXInitSignal() != 1) + { + logError("NXShadowCreate", EGET()); + + return -1; + }*/ + + if (NXCreateInput(keymap, shadowDisplayName) != 1) + { + logError("NXShadowCreate", EGET()); + + return -1; + } + + if (NXCreatePoller(display, shadowDisplay) != 1) + { + logWarning("NXShadowCreate", "NXCreatePoller failed."); + + return -1; + } + + if (NXCreateUpdateManager() != 1) + { + logError("NXShadowCreate", EGET()); + + return -1; + } + + return 1; +} + +#if !defined(__CYGWIN32__) && !defined(WIN32) + +void NXShadowSetDisplayUid(int uid) +{ + NXShadowOptions.optionShadowDisplayUid = uid; +} + +void NXShadowDisableShm(void) +{ + logUser("NXShadowDisableShm: Disabling SHM.\n"); + + NXShadowOptions.optionShmExtension = 0; +} + +void NXShadowDisableDamage(void) +{ + NXShadowOptions.optionDamageExtension = 0; +} + +void NXShadowGetScreenSize(int *w, int *h) +{ + poller -> getScreenSize(w, h); +} + +void NXShadowSetScreenSize(int *w, int *h) +{ + poller -> setScreenSize(w, h); +} + +#endif + +void NXShadowDestroy() +{ + if (poller) + { + delete poller; + + poller = NULL; + } + + if (updateManager) + { + delete updateManager; + + updateManager = NULL; + } + + if (input) + { + delete input; + + input = NULL; + } +} + +void NXShadowHandleInput() +{ + logTrace("NXShadowHandleInput"); + + if (NXShadowNotInitialized()) + { + logError("NXShadowHandleInput - NXShadow not properly initialized.", ESET(EBADF)); + + return; + } + + NXHandleException(); + + updateManager -> handleInput(); + + poller -> handleInput(); +} + +int NXShadowHasChanged(int (*callback)(void *), void *arg, int *suspended) +{ + int result; + + logTrace("NXShadowHasChanged"); + + if (NXShadowNotInitialized()) + { + logError("NXShadowHasChanged - NXShadow not properly initialized.", ESET(EBADF)); + + return -1; + } + + // + // FIXME + //updateManager -> destroyUpdateManagerRegion(); + // + + updateManager -> newRegion(); + +#if !defined(__CYGWIN32__) && !defined(WIN32) + poller -> getEvents(); +#endif + + result = poller -> isChanged(callback, arg, suspended); + + if (result == 1) + { + updateManager -> addRegion(poller -> lastUpdatedRegion()); + + return 1; + } + else if (result == -1) + { + logTest("NXShadowHasChanged", "Scanline error."); + return -1; + } + + return 0; +} + +void NXShadowExportChanges(long *numRects, char **pBox) +{ + Region pReg; + + logTrace("NXShadowExportChanges"); + + if (NXShadowNotInitialized()) + { + logError("NXShadowExportChanges - NXShadow not properly initialized.", ESET(EBADF)); + } + + updateManager -> update(); + pReg = updateManager -> getUpdateManagerRegion(); + *numRects = pReg -> numRects; + *pBox = (char *)pReg -> rects; + + logTest("NXShadowExportChanges", "numRects [%ld] pBox[%p], pReg->numRects[%ld], rects[%p], size[%lu]", + *numRects, *pBox, pReg -> numRects, &(pReg -> rects -> x2), + (unsigned long) sizeof(pReg -> rects -> x2)); +} + +void NXShadowEvent(Display *display, XEvent event) +{ + poller -> handleEvent(display, &event); +} + +void NXShadowWebKeyEvent(KeySym keysym, Bool isKeyPress) +{ + poller -> handleWebKeyEvent(keysym, isKeyPress); +} + +#ifdef __CYGWIN32__ + +int NXShadowCaptureCursor(unsigned int wnd, void *vis) +{ + Window window = (Window)wnd; + Visual *visual = reinterpret_cast(vis); + + logTrace("NXShadowCaptureCursor"); + + logTest("NXShadowCaptureCursor","Init"); + + return poller -> updateCursor(window, visual); +} + +#endif + +void NXShadowUpdateBuffer(void **buffer) +{ + char **fBuffer = reinterpret_cast(buffer); + + if (*fBuffer != NULL) + { + poller -> destroyFrameBuffer(); + + poller -> init(); + } + + *fBuffer = poller -> getFrameBuffer(); + + logTest("NXShadowUpdateBuffer","New frame buffer [0x%p]", (void *)*fBuffer); +} + +void NXShadowInitKeymap(void *keysyms) +{ + NXShadowKeymap = (KeySymsPtr) keysyms; + + logTest("NXShadowInitKeymap","KeySyms pointer [0x%p]", (void *)NXShadowKeymap); +} diff --git a/nxcompshad/src/Updater.cpp b/nxcompshad/src/Updater.cpp new file mode 100644 index 000000000..4b677a78c --- /dev/null +++ b/nxcompshad/src/Updater.cpp @@ -0,0 +1,395 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG +// +#include +// +#include "Updater.h" +#include "Logger.h" + +Updater::Updater(char *displayName, Display *display) +{ + logTrace("Updater::Updater"); + + displayName_ = displayName; + display_ = display; + closeDisplay_ = false; + image_ = NULL; + updateRegion_ = NULL; + buffer_ = NULL; +} + +Updater::~Updater() +{ + logTrace("Updater::~Updater"); + + if (input_) + { + int removedEvents = input_ -> removeAllEvents(display_); + + logTest("Updater::~Updater", "Removed events in input queue is [%d].", removedEvents); + } + + if (display_) + { + XDestroyWindow(display_, window_); + XFreePixmap(display_, pixmap_); + + if (closeDisplay_) + { + XCloseDisplay(display_); + } + } + + if (image_) + { + image_ -> data = NULL; + + XDestroyImage(image_); + } + + if (updateRegion_) + { + XDestroyRegion(updateRegion_); + } +} + +int Updater::init(int width, int height, char *fb, Input *input) +{ + logTrace("Updater::init"); + + if (fb == NULL || input == NULL || width <= 0 || height <= 0) + { + logError("Updater::init", ESET(EINVAL)); + + return -1; + } + + width_ = width; + height_ = height; + buffer_ = fb; + input_ = input; +/* + if (display_ == NULL) + { + display_ = XOpenDisplay(displayName_); + + closeDisplay_ = true; + + if (display_ == NULL) + { + logError("Updater::init", ESET(ENOMSG)); + + return -1; + } + } +*/ + depth_ = DefaultDepth(display_, DefaultScreen(display_)); + + if (depth_ == 8) bpl_ = width_; + else if (depth_ == 16) bpl_ = width_ * 2; + else bpl_ = width_ * 4; + + logTest("Updater::init", "Server geometry [%d, %d] depth [%d] bpl [%d].", width_, height_, depth_, bpl_); + +/* int bitmap_pad = 8; + + image_ = XCreateImage(display_, DefaultVisual(display_, DefaultScreen(display_)), depth_, ZPixmap, 0, + buffer_, width_, height_, bitmap_pad, 0); + + if (image_ == NULL) + { + logError("Updater::init", ESET(ENOMSG)); + + logTest("Updater::init", "Failed to create default image."); + + return -1; + } + + pixmap_ = XCreatePixmap(display_, DefaultRootWindow(display_), width_, height_, depth_); + + unsigned int mask = CWBackPixmap | CWBorderPixel | CWEventMask; + + XSetWindowAttributes attributes; + + attributes.background_pixmap = pixmap_; + attributes.border_pixel = WhitePixel(display_, DefaultScreen(display_)); + attributes.event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask; + + window_ = XCreateWindow(display_, DefaultRootWindow(display_), + 0, 0, width_, height_, 0, depth_, InputOutput, + DefaultVisual(display_, DefaultScreen(display_)), mask, &attributes); + + if (window_ == None) + { + logError("Updater::init", ESET(ENOMSG)); + + return -1; + } + + XSizeHints *size_hints; + + if ((size_hints = XAllocSizeHints()) == NULL) + { + logError("Updater::init", ESET(ENOMEM)); + + return -1; + } + + size_hints -> flags = PMinSize | PMaxSize; + size_hints -> min_width = width_; + size_hints -> max_width = width_; + size_hints -> min_height = height_; + size_hints -> max_height = height_; + + XSetWMNormalHints(display_, window_, size_hints); + + XFree(size_hints); + + Atom deleteWMatom = XInternAtom(display_, "WM_DELETE_WINDOW", 1); + + XSetWMProtocols(display_, window_, &deleteWMatom, 1); + + XMapWindow(display_, window_);*/ + + updateRegion_ = XCreateRegion(); + + logTest("Updater::init", "updateRegion_[%p]", updateRegion_); + return 1; +} + +void Updater::addRegion(Region region) +{ + // + // FIXME: Is this too paranoid ? + // + + if (updateRegion_ == NULL) + { + logError("Updater::addRegion", ESET(EINVAL)); + + return; + } + + XUnionRegion(region, updateRegion_, updateRegion_); +} + +void Updater::update() +{ + logTrace("Updater::update"); + + if (updateRegion_ == NULL) + { + logError("Updater::update", ESET(EINVAL)); + + return; + } + + logTest("Updater::update", "Number of rectangles [%ld].", updateRegion_ -> numRects); + +/* for (; updateRegion_ -> numRects > 0; updateRegion_ -> numRects--) + { + int n = updateRegion_ -> numRects - 1; + + int x = updateRegion_ -> rects[n].x1; + int y = updateRegion_ -> rects[n].y1; + unsigned int width = updateRegion_ -> rects[n].x2 - updateRegion_ -> rects[n].x1; + unsigned int height = updateRegion_ -> rects[n].y2 - updateRegion_ -> rects[n].y1; + + logDebug("Updater::update", "Sending rectangle: [%d, %d, %d, %d].", x, y, width, height); + + // + // We need to update the extents. + // + + int bitmap_pad; + + if (depth_ == 32 || depth_ == 24) + { + bitmap_pad = 32; + } + else if (depth_ == 16) + { + if ((width & 1) == 0) + { + bitmap_pad = 32; + } + else + { + bitmap_pad = 16; + } + } + else if ((width & 3) == 0) + { + bitmap_pad = 32; + } + else if ((width & 1) == 0) + { + bitmap_pad = 16; + } + else + { + bitmap_pad = 8; + }*/ + +/* image_ -> bitmap_pad = bitmap_pad;*/ + + /* NXShadowCorrectColor(x, y, width, height);*/ + +/* XPutImage(display_, pixmap_, DefaultGC(display_, DefaultScreen(display_)), + image_, x, y, x, y, width, height); + + XClearArea(display_, window_, x, y, width, height, 0); + }*/ + + // + // Should we reduces the box vector ? + // + // BOX *box = Xrealloc(updateRegion_ -> rects, + // updateRegion_ -> numRects == 0 ? sizeof(BOX) : + // updateRegion_ -> numRects * sizeof(BOX)); + // + // if (box) + // { + // updateRegion_ -> rects = box; + // updateRegion_ -> size = 1; + // } + // + + if (updateRegion_ -> numRects == 0) + { + updateRegion_ -> extents.x1 = 0; + updateRegion_ -> extents.y1 = 0; + updateRegion_ -> extents.x2 = 0; + updateRegion_ -> extents.y2 = 0; + } + else + { + // + // FIXME: We have to update the region extents. + // + + logTest("Updater::update", "Region extents has not been updated."); + } +} + +void Updater::handleInput() +{ + logTrace("Updater::handleInput"); + + XEvent *event = new XEvent; + + if (event == NULL) + { + logError("Updater::handleInput", ESET(ENOMEM)); + + return; + } + + while (XCheckIfEvent(display_, event, anyEventPredicate, NULL)) + { + switch (event -> type) + { + /* case ClientMessage: + { + Atom wmProtocols = XInternAtom(display_, "WM_PROTOCOLS", 0); + Atom wmDeleteWindow = XInternAtom(display_, "WM_DELETE_WINDOW", 0); + + if (event -> xclient.message_type == wmProtocols && + (Atom)event -> xclient.data.l[0] == wmDeleteWindow) + { + logTest("Updater::handleInput", "Got client message of type WM_PROTOCOLS and value WM_DELETE_WINDOW," + " throwing exception UpdaterClosing."); + + delete event; + + throw UpdaterClosing(); + } + else + { + logTest("Updater::handleInput", "Unexpected client message type [%ld] format [%d] first value [%ld]", + event -> xclient.message_type, event -> xclient.format, event -> xclient.data.l[0]); + } + + break; + }*/ + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + { + input_ -> pushEvent(display_, event); + + event = new XEvent; + + if (event == NULL) + { + logError("Updater::handleInput", ESET(ENOMEM)); + + return; + } + + break; + } + default: + { + logTest("Updater::handleInput", "Handling unexpected event [%d].", event -> type); + + break; + } + } + } + + delete event; +} + +void Updater::newRegion() +{ + if (updateRegion_ != NULL) + { + XDestroyRegion(updateRegion_); + } + + updateRegion_ = XCreateRegion(); + + logTest("Updater::newRegion", "updateRegion_ [%p].", updateRegion_); +} +// +// Private functions. +// diff --git a/nxcompshad/src/Updater.h b/nxcompshad/src/Updater.h new file mode 100644 index 000000000..10d75c0d6 --- /dev/null +++ b/nxcompshad/src/Updater.h @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef Updater_H +#define Updater_H + +#include + +#include "Regions.h" +#include "Input.h" + +class UpdaterClosing {}; + +class Updater +{ + public: + + Updater(char *displayName, Display *display); + + ~Updater(); + + int init(int, int, char *, Input*); + + void addRegion(Region r); + + void update(); + + void handleInput(); + + XImage *getImage(); + + Region getUpdateRegion(); + + void newRegion(); + + private: + + Input *input_; + + static inline Bool anyEventPredicate(Display*, XEvent*, XPointer); + + void handleKeyboardEvent(XEvent &event); + + char *displayName_; + + char *buffer_; + + bool closeDisplay_; + + Display *display_; + + int depth_; + + int width_; + int height_; + + int bpl_; + + Window window_; + XImage *image_; + + Pixmap pixmap_; + + Region updateRegion_; + +}; + +Bool Updater::anyEventPredicate(Display*, XEvent*, XPointer) +{ + return true; +} + +inline XImage* Updater::getImage() +{ + return image_; +} +inline Region Updater::getUpdateRegion() +{ + return updateRegion_; +} +#endif /* Updater_H */ diff --git a/nxcompshad/src/Win.cpp b/nxcompshad/src/Win.cpp new file mode 100644 index 000000000..6033f2c1b --- /dev/null +++ b/nxcompshad/src/Win.cpp @@ -0,0 +1,1149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(__CYGWIN32__) || defined(WIN32) + +#include + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include "Poller.h" +#include "Logger.h" + +Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display) +{ + logTrace("Poller::Poller"); + + screenDC_ = NULL; + screenBmp_ = NULL; + memoryDC_ = NULL; + pDIBbits_ = NULL; + DIBBuffer_ = NULL; + pKey_ = NULL; + pMouse_ = NULL; + path_ = NULL; + keymapName_ = input -> getKeymap(); + keymap_ = NULL; + toggleButtonState_ = 0; + serverModifierState_ = 0; + display_ = display; + depth_ = DefaultDepth(display_, DefaultScreen(display_)); + oldCursor_ = 0; + xCursor_ = 0; +} + +Poller::~Poller() +{ + logTrace("Poller::~Poller"); + + if (screenDC_) + { + BOOL result = ReleaseDC(NULL, screenDC_); + + logTest("Poller::~Poller", "ReleaseDC returned [%d].", result); + + screenDC_ = NULL; + } + + if (memoryDC_) + { + BOOL result = DeleteDC(memoryDC_); + + logTest("Poller::~Poller", "DeleteDC returned [%d].", result); + + memoryDC_ = NULL; + } + + if (screenBmp_) + { + BOOL result = DeleteObject(screenBmp_); + + logTest("Poller::~Poller", "DeleteObject returned [%d].", result); + + screenBmp_ = NULL; + } + + if (DIBBuffer_) + { + logDebug("Poller::~Poller", "Delete DIBBuffer_ [%p].", DIBBuffer_); + + delete [] DIBBuffer_; + } + + if (pKey_) + { + logDebug("Poller::~Poller", " pKey_[%p].", pKey_); + + delete [] pKey_; + } + + if (pMouse_) + { + logDebug("Poller::~Poller", " pMouse_[%p].", pMouse_); + + delete [] pMouse_; + } + + if (keymap_) + { + logDebug("Poller::~Poller", " keymap_[%p].", keymap_); + + delete [] keymap_; + } +} + +int Poller::init() +{ + logTrace("Poller::init"); + + int maxLengthArrayINPUT = 6; + + platformOS(); + + pKey_ = new INPUT [maxLengthArrayINPUT]; + + if (pKey_ == NULL) + { + logError("Poller::init", ESET(ENOMEM)); + + return -1; + } + + for (int i = 0; i < maxLengthArrayINPUT; i++) + { + pKey_[i].type = INPUT_KEYBOARD; + pKey_[i].ki.wVk = (WORD) 0; + pKey_[i].ki.time = (DWORD) 0; + pKey_[i].ki.dwExtraInfo = (DWORD) 0; + } + + pMouse_ = new INPUT; + + if (pMouse_ == NULL) + { + logError("Poller::init", ESET(ENOMEM)); + + return -1; + } + + pMouse_ -> type = INPUT_MOUSE; + + pMouse_ -> mi.dx = 0; + pMouse_ -> mi.dy = 0; + pMouse_ -> mi.mouseData = (DWORD) 0; + pMouse_ -> mi.time = 0; + pMouse_ -> mi.dwExtraInfo = (ULONG_PTR) NULL; + + screenDC_ = GetDC(NULL); + + if (screenDC_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + switch(depth_) + { + case 8: + { + depth_ = 16; + break; + } + case 16: + { + depth_ = 16; + break; + } + case 24: + { + depth_ = 32; + break; + } + default: + { + logError("Poller::init", ESET(EINVAL)); + + return -1; + } + } + + width_ = GetDeviceCaps(screenDC_, HORZRES); + height_ = GetDeviceCaps(screenDC_, VERTRES); + + bpl_ = width_ * (depth_ >> 3); + bpp_ = (depth_ >> 3); + + logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].", + width_, height_, depth_, bpl_, bpp_); + + logTest("Poller::init", "Got device context at [%p] screen size is (%d,%d).", + screenDC_, width_, height_); + + memoryDC_ = CreateCompatibleDC(screenDC_); + + if (memoryDC_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + // + // Delete the old bitmap for the memory device. + // + + HBITMAP bitmap = (HBITMAP) GetCurrentObject(memoryDC_, OBJ_BITMAP); + + if (bitmap && DeleteObject(bitmap) == 0) + { + logError("Poller::init", ESET(ENOMSG)); + } + + // + // Bitmap header describing the bitmap we want to get from GetDIBits. + // + + bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi_.bmiHeader.biWidth = width_; + bmi_.bmiHeader.biHeight = -height_; + bmi_.bmiHeader.biPlanes = 1; + bmi_.bmiHeader.biBitCount = depth_; + bmi_.bmiHeader.biCompression = BI_RGB; + bmi_.bmiHeader.biSizeImage = 0; + bmi_.bmiHeader.biXPelsPerMeter = 0; + bmi_.bmiHeader.biYPelsPerMeter = 0; + bmi_.bmiHeader.biClrUsed = 0; + bmi_.bmiHeader.biClrImportant = 0; + + screenBmp_ = CreateDIBSection(memoryDC_, &bmi_, DIB_RGB_COLORS, &pDIBbits_, NULL, 0); + ReleaseDC(NULL,memoryDC_); + + if (screenBmp_ == NULL) + { + logTest ("Poller::init", "This video device is not supporting DIB section"); + + pDIBbits_ = NULL; + + screenBmp_ = CreateCompatibleBitmap(screenDC_, width_, height_); + + if (screenBmp_ == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + if (SelectObject(memoryDC_, screenBmp_) == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + } + else + { + logTest ("Poller::init", "Enabled the DIB section"); + + if (SelectObject(memoryDC_, screenBmp_) == NULL) + { + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + } + + // + // Check if the screen device raster capabilities + // support the bitmap transfer. + // + + if ((GetDeviceCaps(screenDC_, RASTERCAPS) & RC_BITBLT) == 0) + { + logTest("Poller::init", "This video device is not supporting the bitmap transfer."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + // + // Check if the memory device raster capabilities + // support the GetDIBits and SetDIBits functions. + // + + if ((GetDeviceCaps(memoryDC_, RASTERCAPS) & RC_DI_BITMAP) == 0) + { + logTest("Poller::init", "This memory device is not supporting the GetDIBits and SetDIBits " + "function."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + if (GetDeviceCaps(screenDC_, PLANES) != 1) + { + logTest("Poller::init", "This video device has more than 1 color plane."); + + logError("Poller::init", ESET(ENOMSG)); + + return -1; + } + + return CorePoller::init(); +} + +// +// FIXME: Remove me. +// + +void ErrorExit(LPTSTR lpszFunction) +{ + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + logTest(lpszFunction, " Failed with error [%ld]: %s", dw, (char*)lpMsgBuf); + + LocalFree(lpMsgBuf); + ExitProcess(dw); +} + +// +// FIXME: End. +// + +char *Poller::getRect(XRectangle r) +{ + logTrace("Poller::getRect"); + + logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].", + r.x, r.y, r.width, r.height); + + // + // The CAPTUREBLT operation could be a very + // cpu-consuming task. We should make some + // test to see how much it is expensive. + // Anyway we get tooltip windows and any + // other special effect not included with + // only the SRCCOPY operation. + // + + if (BitBlt(memoryDC_, r.x, r.y, r.width, r.height, + screenDC_, r.x, r.y, SRCCOPY | CAPTUREBLT) == 0) + { + logError("Poller::getRect", ESET(ENOMSG)); + + logTest("Poller::getRect", "Failed to perform a bit-block transfer."); + logTest("Poller::getRect", "bit-block error=%lu", GetLastError()); + + return NULL; + } + + // bmi_.bmiHeader.biWidth = r.width; + // bmi_.bmiHeader.biHeight = -r.height; + + if (pDIBbits_ == NULL) + { + static long nPixel = 0; + + if (nPixel < r.width * r.height) + { + + if (DIBBuffer_) + { + delete [] DIBBuffer_; + } + + nPixel = r.width * r.height; + + DIBBuffer_ = new char [nPixel * bpp_]; + + if (DIBBuffer_ == NULL) + { + logError("Poller::getRect", ESET(ENOMEM)); + + nPixel = 0; + + return NULL; + } + } + + if (GetDIBits(memoryDC_, screenBmp_, height_ - r.height - r.y, r.height, + DIBBuffer_, &bmi_, DIB_RGB_COLORS) == 0) + { + logError("Poller::getRect", ESET(ENOMSG)); + + logTest("Poller::getRect", "Failed to retrieve the screen bitmap."); + + return NULL; + } + + return DIBBuffer_; + } + else + { + return (char *) pDIBbits_ + r.y * bpl_ + r.x * bpp_; + } +} + +void Poller::handleKeyboardEvent(Display *display, XEvent *event) +{ + KeySym keysym; + char *keyname = new char [31]; + keyTranslation tr = {0, 0}; + unsigned char scancode = 0; + int lengthArrayINPUT = 0; + + if (XLookupString((XKeyEvent *) event, keyname, 30, &keysym, NULL) > 0) + { + logTest("Poller::handleKeyboardEvent", "keyname %s, keysym [%x]", keyname, (unsigned int)keysym); + } + + if (specialKeys(keysym, event -> xkey.state, event -> type) == 1) + { + delete[] keyname; + return; + } + + tr = xkeymapTranslateKey(keysym, event -> xkey.keycode, event -> xkey.state); + scancode = tr.scancode; + + logTest("Poller::handleKeyboardEvent", "keyname [%s] scancode [0x%x], keycode[0x%x], keysym [%x]", keyname, + tr.scancode, event ->xkey.keycode, (unsigned int)keysym); + + if (scancode == 0) + { + delete[] keyname; + return; + } + + if (event -> type == KeyPress) + { + int test1 = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); + int test2 = MapVirtualKey(0x24, MAPVK_VSC_TO_VK_EX); + + if (test1 == test2) + { + simulateCtrlAltDel(); + } + + if (isModifier(scancode) == 0) + { + savedServerModifierState_ = serverModifierState_; + } + + ensureServerModifiers(tr, &lengthArrayINPUT); + if (sendInput(scancode, 1, &lengthArrayINPUT) == 0) + { + logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); + } + restoreServerModifiers(scancode); + } + else if (event -> type == KeyRelease) + { + if (sendInput(scancode, 0, &lengthArrayINPUT) == 0) + { + logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT); + } + } + + updateModifierState(scancode, (event -> type == KeyPress)); + + delete[] keyname; +} + +void Poller::handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) +{ +/* +FIXME +*/ +} + +void Poller::handleMouseEvent(Display *display, XEvent *event) +{ + DWORD flg = 0; + DWORD whl = 0; + + if (event -> type == ButtonPress) + { + logTest("Poller::handleMouseEvent", "ButtonPress.\n"); + switch (event -> xbutton.button) + { + case Button1: + { + flg = MOUSEEVENTF_LEFTDOWN; + break; + } + case Button2: + { + flg = MOUSEEVENTF_MIDDLEDOWN; + break; + } + case Button3: + { + flg = MOUSEEVENTF_RIGHTDOWN; + break; + } + case Button4: + { + flg = MOUSEEVENTF_WHEEL; + whl = WHEEL_DELTA; + pMouse_ -> mi.mouseData = whl; + break; + } + case Button5: + { + flg = MOUSEEVENTF_WHEEL; + whl = (DWORD) (-WHEEL_DELTA); + pMouse_ -> mi.mouseData = whl; + break; + } + } + } + else if (event -> type == ButtonRelease) + { + switch (event -> xbutton.button) + { + case Button1: + { + flg = MOUSEEVENTF_LEFTUP; + break; + } + case Button2: + { + flg = MOUSEEVENTF_MIDDLEUP; + break; + } + case Button3: + { + flg = MOUSEEVENTF_RIGHTUP; + break; + } + case Button4: + { + flg = MOUSEEVENTF_WHEEL; + whl = 0; + pMouse_ -> mi.mouseData = whl; + break; + } + case Button5: + { + flg = MOUSEEVENTF_WHEEL; + whl = 0; + pMouse_ -> mi.mouseData = whl; + break; + } + } + } + else if (event -> type == MotionNotify) + { + logTest("Poller::handleMouseEvent", "SetCursor - MotionNotify"); + + SetCursorPos(event -> xmotion.x, event -> xmotion.y); + } + + if (flg > 0) + { + // logTest("Poller::handleMouseEvent", "SetCursor - flg > 0"); + // + // FIXME: move the cursor to the pace the event occurred + // + + SetCursorPos(event -> xbutton.x, event -> xbutton.y); + + // + // FIXME: Remove me: send the click/release event + // mouse_event(flg, 0, 0, whl, (ULONG_PTR)NULL); + // + + pMouse_ -> mi.dwFlags = flg; + + if (SendInput(1, pMouse_, sizeof(INPUT)) == 0) + { + logTest("Poller::handleMouseEvent", "Failed SendInput"); + } + } +} + +int Poller::updateCursor(Window wnd, Visual* vis) +{ + BYTE *mBits, *andBits, *xorBits; + + logTrace("Poller::Cursor"); + + // + // Retrieve mouse cursor handle. + // + + CURSORINFO cursorInfo; + cursorInfo.cbSize = sizeof(CURSORINFO); + + if (GetCursorInfo(&cursorInfo) == 0) + { + logTest("Poller::Cursor", "GetCursorInfo() failed [%u].\n", (unsigned int)GetLastError()); + LocalFree(&cursorInfo); + return -1; + } + + HCURSOR hCursor = cursorInfo.hCursor; + + if (hCursor == 0) + { + logTest("Poller::Cursor","Cursor Handle is NULL. Error[%u].\n", (unsigned int)GetLastError()); + return 1; + } + + if (hCursor == oldCursor_) + { + LocalFree(&cursorInfo); + return 1; + } + else + { + oldCursor_ = hCursor; + } + + // + // Get cursor info. + // + + // logTest("Poller::Cursor","hCursor [%xH] GetCursor [%xH].\n", hCursor, GetCursor()); + + ICONINFO iconInfo; + if (GetIconInfo(hCursor, &iconInfo) == 0) + { + logTest("Poller::Cursor","GetIconInfo() failed. Error[%d].", (unsigned int)GetLastError()); + LocalFree(&iconInfo); + // return -1; + } + + BOOL isColorCursor = FALSE; + if (iconInfo.hbmColor != NULL) + { + isColorCursor = TRUE; + } + + if (iconInfo.hbmMask == NULL) + { + logTest("Poller::Cursor","Cursor bitmap handle is NULL.\n"); + return -1; + } + + // + // Check bitmap info for the cursor + // + + BITMAP bmMask; + if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), (LPVOID)&bmMask)) + { + logTest("Poller::Cursor","GetObject() for bitmap failed.\n"); + DeleteObject(iconInfo.hbmMask); + LocalFree(&bmMask); + return -1; + } + + if (bmMask.bmPlanes != 1 || bmMask.bmBitsPixel != 1) + { + logTest("Poller::Cursor","Incorrect data in cursor bitmap.\n"); + LocalFree(&bmMask); + DeleteObject(iconInfo.hbmMask); + return -1; + } + + // Get monochrome bitmap data for cursor + // NOTE: they say we should use GetDIBits() instead of GetBitmapBits(). + mBits = new BYTE[bmMask.bmWidthBytes * bmMask.bmHeight]; + + if (mBits == NULL)//Data bitmap + { + DeleteObject(iconInfo.hbmMask); + DestroyCursor(cursorInfo.hCursor); + LocalFree(&iconInfo); + LocalFree(&bmMask); + delete[] mBits; + return -1; + } + + BOOL success = GetBitmapBits(iconInfo.hbmMask, bmMask.bmWidthBytes * bmMask.bmHeight, mBits); + + if (!success) + { + logTest("Poller::Cursor","GetBitmapBits() failed.\n"); + delete[] mBits; + return -1; + } + + andBits = mBits; + + long width = bmMask.bmWidth; + long height = (isColorCursor) ? bmMask.bmHeight : bmMask.bmHeight/2; + + // + // The bitmask is formatted so that the upper half is + // the icon AND bitmask and the lower half is the icon XOR bitmask. + // + + if (!isColorCursor) + { + xorBits = andBits + bmMask.bmWidthBytes * height; + +/* logTest("Poller::Cursor","no color widthB[%ld] width[%ld] height[%ld] totByte[%ld] mbits[%ld].\n", + bmMask.bmWidthBytes,width,height,success,bmMask.bmHeight * bmMask.bmWidthBytes);*/ + + if (xCursor_ > 0) + { + XFreeCursor(display_, xCursor_); + } + + xCursor_ = createCursor(wnd, vis, (unsigned int)iconInfo.xHotspot, (unsigned int)iconInfo.yHotspot, + width, height, (unsigned char *)xorBits, (unsigned char *)andBits); + + XDefineCursor(display_, wnd, xCursor_); + } + + delete []mBits; + DeleteObject(iconInfo.hbmMask); + LocalFree(&bmMask); + DestroyCursor(cursorInfo.hCursor); + LocalFree(&iconInfo); + + return success; +} + +unsigned char Poller::specialKeys(unsigned int keysym, unsigned int state, int pressed) +{ + return 0; +} + +void Poller::ensureServerModifiers(keyTranslation tr, int *lengthArrayINPUT) +{ + return; +} + +void Poller::restoreServerModifiers(UINT scancode) +{ + keyTranslation dummy; + int lengthArrayINPUT = 0; + + if (isModifier(scancode) == 1) + { + return; + } + + dummy.scancode = 0; + dummy.modifiers = savedServerModifierState_; + ensureServerModifiers(dummy, &lengthArrayINPUT); + if (sendInput(0, 0, &lengthArrayINPUT) == 0) + { + logTest("Poller::restoreServerModifiers", "lengthArrayINPUT [%d]", lengthArrayINPUT); + } +} + +int Poller::updateShadowFrameBuffer(void) +{ + return 1; +} + +void Poller::addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname) +{ + return; +} + +FILE *Poller::xkeymapOpen(char *filename) +{ + return NULL; +} + +int Poller::xkeymapRead(char *mapname) +{ + return 1; +} + +void Poller::xkeymapInit(char *keyMapName) +{ + return; +} + +keyTranslation Poller::xkeymapTranslateKey(unsigned int keysym, unsigned int keycode, + unsigned int state) +{ + keyTranslation tr = { 0, 0 }; + + return tr; +} + +unsigned char Poller::getKeyState(unsigned int state, unsigned int keysym) +{ + return 0; +} + +char *Poller::getKsname(unsigned int keysym) +{ + char *ksname = NULL; + + return ksname; +} + +// +// Routine used to fool Winlogon into thinking CtrlAltDel was pressed +// +char Poller::simulateCtrlAltDel(void) +{ + HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); + + // + // Switch into the Winlogon desktop. + // + if (selectDesktopByName("Winlogon") == 0) + { + logTest("SimulateCtrlAltDelThreadFn","Failed to select logon desktop."); + return 0; + } + + logTest("SimulateCtrlAltDelThreadFn","Generating ctrl-alt-del."); + + // + // Winlogon uses hotkeys to trap Ctrl-Alt-Del. + // + PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE)); + + // + // Switch back to our original desktop. + // + if (oldDesktop != NULL) + { + selectDesktop(oldDesktop); + } + + return 1; +} + +// Switches the current thread into a different desktop by desktop handle +// This call takes care of all the evil memory management involved +char Poller::selectDesktop(HDESK newDesktop) +{ + // + // Only on NT. + // + if (isWinNT()) + { + HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId()); + + DWORD dummy; + char newName[256]; + + if (GetUserObjectInformation(newDesktop, UOI_NAME, &newName, 256, &dummy) == 0) + { + logDebug("Poller::selectDesktop","GetUserObjectInformation() failed. Error[%lu].", GetLastError()); + return 0; + } + + logTest("Poller::selectDesktop","New Desktop to [%s] (%x) from (%x).", + newName, (unsigned int)newDesktop, (unsigned int)oldDesktop); + + // + // Switch the desktop. + // + if(SetThreadDesktop(newDesktop) == 0) + { + logDebug("Poller::SelectDesktop","Unable to SetThreadDesktop(), Error=%lu.", GetLastError()); + return 0; + } + + // + // Switched successfully - destroy the old desktop. + // + if (CloseDesktop(oldDesktop) == 0) + { + logDebug("Poller::selectHdesk","Failed to close old desktop (%x), Error=%lu.", + (unsigned int)oldDesktop, GetLastError()); + return 0; + } + } + + return 1; +} + +// +// Switches the current thread into a different desktop, by name +// Calling with a valid desktop name will place the thread in that desktop. +// Calling with a NULL name will place the thread in the current input desktop. +// + +char Poller::selectDesktopByName(char *name) +{ + // + // Only on NT. + // + if (isWinNT()) + { + HDESK desktop; + + if (name != NULL) + { + // + // Attempt to open the named desktop. + // + desktop = OpenDesktop(name, 0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + } + else + { + // + // Open the input desktop. + // + desktop = OpenInputDesktop(0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + } + + if (desktop == NULL) + { + logDebug("Poller::selectDesktopByName","Unable to open desktop, Error=%lu.", GetLastError()); + return 0; + } + + // + // Switch to the new desktop + // + if (selectDesktop(desktop) == 0) + { + // + // Failed to enter the new desktop, so free it! + // + logDebug("Poller::selectDesktopByName","Failed to select desktop."); + + if (CloseDesktop(desktop) == 0) + { + logDebug("Poller::selectDesktopByName","Failed to close desktop, Error=%lu.", GetLastError()); + return 0; + } + } + + return 1; + } + + return (name == NULL); +} + +void Poller::platformOS() +{ + OSVERSIONINFO osversioninfo; + osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo); + + // + // Get the current OS version. + // + if (GetVersionEx(&osversioninfo) == 0) + { + platformID_ = 0; + } + platformID_ = osversioninfo.dwPlatformId; + +// +// versionMajor = osversioninfo.dwMajorVersion; +// versionMinor = osversioninfo.dwMinorVersion; +// +} + +char Poller::checkDesktop() +{ + // + // Only on NT. + // + if (isWinNT()) + { + // + // Get the input and thread desktops. + // + HDESK desktop = GetThreadDesktop(GetCurrentThreadId()); + HDESK inputDesktop = OpenInputDesktop(0, FALSE, + DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | + DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | + DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS | + DESKTOP_SWITCHDESKTOP | GENERIC_WRITE); + + if (inputDesktop == NULL) + { + return 0; + } + + DWORD dummy; + char desktopName[256]; + char inputName[256]; + + if (GetUserObjectInformation(desktop, UOI_NAME, &desktopName, 256, &dummy) == 0) + { + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + if (GetUserObjectInformation(inputDesktop, UOI_NAME, &inputName, 256, &dummy) == 0) + { + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + if (strcmp(desktopName, inputName) != 0) + { + // + // Switch to new desktop. + // + selectDesktop(inputDesktop); + } + + if (CloseDesktop(desktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + + if (CloseDesktop(inputDesktop) == 0) + { + logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError()); + return 0; + } + } + + return 1; +} + +unsigned char Poller::isModifier(UINT scancode) +{ + return 0; +} + +void Poller::updateModifierState(UINT scancode, unsigned char pressed) +{ + return; +} + +Cursor Poller::createCursor(Window wnd, Visual *vis,unsigned int x, unsigned int y, + int width, int height, unsigned char *xormask, unsigned char *andmask) +{ + Pixmap maskglyph, cursorglyph; + XColor bg, fg; + Cursor xcursor; + unsigned char *cursor; + unsigned char *mask, *pmask, *pcursor, tmp; + int scanline, offset; + + scanline = (width + 7) / 8; + offset = scanline * height; + + pmask = andmask; + pcursor = xormask; + for (int i = 0; i < offset; i++) + { + // + // The pixel is black if both the bit of andmask and xormask is one. + // + + tmp = *pcursor & *pmask; + *pcursor ^= tmp; + *pmask ^= tmp; + + *pmask = ~(*pmask); + + pmask++; + pcursor++; + } + + cursor = new unsigned char[offset]; + memcpy(cursor, xormask, offset); + + mask = new unsigned char[offset]; + memcpy(mask, andmask, offset); + + fg.red = fg.blue = fg.green = 0xffff; + bg.red = bg.blue = bg.green = 0x0000; + fg.flags = bg.flags = DoRed | DoBlue | DoGreen; + + cursorglyph = createGlyph(wnd, vis, width, height, cursor); + maskglyph = createGlyph(wnd, vis, width, height, mask); + + xcursor = XCreatePixmapCursor(display_, cursorglyph, maskglyph, &fg, &bg, x, y); + + XFreePixmap(display_, maskglyph); + XFreePixmap(display_, cursorglyph); + delete[]mask; + delete[]cursor; + + return xcursor; +} + +Pixmap Poller::createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data) +{ + XImage *image; + Pixmap bitmap; + int scanline; + GC glyphGC; + + scanline = (width + 7) / 8; + + bitmap = XCreatePixmap(display_, wnd, width, height, 1); + glyphGC = XCreateGC(display_, bitmap, 0, NULL); + + image = XCreateImage(display_, visual, 1, ZPixmap, 0, (char *)data, width, height, 8, scanline); + image->byte_order = 1; // MSBFirst -- LSBFirst = 0 + image->bitmap_bit_order = 1; + XInitImage(image); + +/* logTest("Poller::createGlyph","XPutImage on pixmap %d,%d,%d,%d.\n", + 0, 0, width, height);*/ + XPutImage(display_, bitmap, glyphGC, image, 0, 0, 0, 0, width, height); + XFree(image); + + return bitmap; +} +#endif /* defined(__CYGWIN32__) || defined(WIN32) */ diff --git a/nxcompshad/src/Win.h b/nxcompshad/src/Win.h new file mode 100644 index 000000000..615f9a5f5 --- /dev/null +++ b/nxcompshad/src/Win.h @@ -0,0 +1,232 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef __CYGWIN32__ + +#ifndef Win32Poller_H +#define Win32Poller_H + +//#include + +#include +#include +#include +#include + +#define CAPTUREBLT 0x40000000 + +#define KEYEVENTF_SCANCODE 0x00000008 +#define MAPVK_VSC_TO_VK_EX 3 +// +// The CAPTUREBLT is a raster operation used +// in bit blit transfer. +// +// Using this operation includes any windows +// that are layered on top of your window in +// the resulting image. By default, the image +// only contains your window. +// + +#include "Core.h" + +typedef struct _keyTranslation +{ + unsigned char scancode; + unsigned short modifiers; + +}keyTranslation; + +class Poller : public CorePoller +{ + public: + + Display *display_; + keyTranslation *keymap_; + unsigned char keymapLoaded_; + int minKeycode_; + + Poller(Input *, Display *display, int = 16); + + ~Poller(); + + int init(); + + int updateCursor(Window, Visual*); + + private: + + + int Poller::updateShadowFrameBuffer(void); + void handleKeyboardEvent(Display *, XEvent *); + void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress); + void addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname); + int xkeymapRead(char *mapname); + FILE *xkeymapOpen(char *filename); + void xkeymapInit(char *keyMapName); + keyTranslation xkeymapTranslateKey(unsigned int keysym, unsigned int keycode, unsigned int state); + unsigned char getKeyState(unsigned int state, unsigned int keysym); + char *getKsname(unsigned int keysym); + unsigned char specialKeys(unsigned int keysym, unsigned int state, int pressed); + + unsigned char toggleSwitch(unsigned char ToggleStateClient, unsigned char ToggleStateServer, UINT scancode, + int *lengthArrayINPUT); + + void updateModifierState(UINT, unsigned char); + + unsigned char toggleServerState(UINT scancode); + unsigned char keyState(UINT scancode, UINT mapType); + unsigned char keyStateAsync(UINT scancode); + + void handleMouseEvent(Display *, XEvent *); + + Cursor createCursor(Window wnd, Visual *vis, unsigned int x, unsigned int y, int width, + int height, unsigned char *xormask, unsigned char *andmask); + + Pixmap createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data); + + char isWinNT(); + char selectDesktop(HDESK new_desktop); + char selectDesktopByName(char *name); + void platformOS(); + char simulateCtrlAltDel(void); + DWORD platformID_; + + INPUT *pKey_, *pMouse_; + + char *keymapName_; + char *path_; + + unsigned char toggleButtonState_; + unsigned short serverModifierState_; + unsigned short savedServerModifierState_; + + void ensureServerModifiers(keyTranslation tr, int *lenghtArrayINPUT); + void restoreServerModifiers(UINT scancode); + unsigned char isModifier(UINT scancode); + + char sendInput(unsigned char scancode, unsigned char pressed, int *lengthArrayINPUT); + + char *getRect(XRectangle); + char checkDesktop(); + + char *DIBBuffer_; + + HCURSOR oldCursor_; + + VOID *pDIBbits_; + HDC screenDC_; + HDC memoryDC_; + BITMAPINFO bmi_; + HBITMAP screenBmp_; + + Cursor xCursor_; + +}; + +#undef TEST + +inline unsigned char Poller::toggleSwitch(unsigned char ToggleStateClient, unsigned char ToggleStateServer, + UINT scancode, int *lengthArrayINPUT) +{ + return 1; +} + +inline unsigned char Poller::toggleServerState(UINT scancode) +{ + return (GetKeyState(MapVirtualKeyEx(scancode, 3, GetKeyboardLayout((DWORD)NULL))) & 0x1); +} + +inline unsigned char Poller::keyStateAsync(UINT vKeycode) +{ + return GetAsyncKeyState(vKeycode); +} + +inline unsigned char Poller::keyState(UINT code, UINT mapType) +{ + if (mapType == 0) + { + // + // Virtual Keycode + // + return ((GetKeyState(code) & 0x80) == 0x80); + } + else + { + // + // scancode + // + return ((GetKeyState(MapVirtualKeyEx(code, 3, GetKeyboardLayout((DWORD)NULL))) & 0x80) == 0x80); + } +} + +inline char Poller::isWinNT() +{ + return (platformID_ == VER_PLATFORM_WIN32_NT); +} + +inline char Poller::sendInput(unsigned char scancode, unsigned char pressed, int *lengthArrayINPUT) +{ + DWORD keyEvent = 0; + DWORD extended = 0; + + if (scancode > 0) + { + if (pressed == 0) + { + keyEvent = KEYEVENTF_KEYUP; + } + + if (scancode & 0x80) + { + scancode &= ~0x80; + extended = KEYEVENTF_EXTENDEDKEY; + } + + pKey_[*lengthArrayINPUT].ki.wScan = (WORD) scancode; + pKey_[*lengthArrayINPUT].ki.dwFlags = (DWORD) (keyEvent | KEYEVENTF_SCANCODE | extended); + (*lengthArrayINPUT)++; + } + + + if (*lengthArrayINPUT > 0) { + // FIXME: Remove me. + logTest("Poller::sendInput", "length Input [%d] event: %s", *lengthArrayINPUT, + pressed == 1 ? "KeyPress": "KeyRelease"); + + if (SendInput(*lengthArrayINPUT, pKey_, sizeof(INPUT)) == 0) + { + logTest("Poller::sendInput", "Failed SendInput, event: %s", pressed == 1 ? "KeyPress": "KeyRelease"); + *lengthArrayINPUT = 0; + return 0; + } + + *lengthArrayINPUT = 0; + } + + return 1; +} +#endif /* Win32Poller_H */ + +#endif /* __CYGWIN32__ */ diff --git a/nxcompshad/src/X11.cpp b/nxcompshad/src/X11.cpp new file mode 100644 index 000000000..3643df731 --- /dev/null +++ b/nxcompshad/src/X11.cpp @@ -0,0 +1,1598 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if !defined(__CYGWIN32__) && !defined(WIN32) + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#include +#include +#include +#include "X11/include/XTest_nxcompshad.h" +#include +#include +#include + +#include "Poller.h" +#include "Logger.h" +#include "Shadow.h" + +#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) + +#undef TRANSLATE_KEYCODES +#define TRANSLATE_ALWAYS + +typedef struct { + KeySym *map; + KeyCode minKeyCode, + maxKeyCode; + int mapWidth; +} KeySymsRec, *KeySymsPtr; + +extern KeySymsPtr NXShadowKeymap; + +typedef struct _KeyPressed +{ + KeyCode keyRcvd; + KeyCode keySent; + struct _KeyPressed *next; +} KeyPressedRec; + +static KeyPressedRec *shadowKeyPressedPtr = NULL; + +static KeySym *shadowKeysyms = NULL; +static KeySym *masterKeysyms = NULL; + +static KeySym *shadowKeymap = NULL; + +static int shadowMinKey, shadowMaxKey, shadowMapWidth; +static int masterMinKey, masterMaxKey, masterMapWidth; + +static int leftShiftOn = 0; +static int rightShiftOn = 0; +static int modeSwitchOn = 0; +static int level3ShiftOn = 0; +static int altROn = 0; + +static int sentFakeLShiftPress = 0; +static int sentFakeLShiftRelease = 0; +static int sentFakeRShiftRelease = 0; +static int sentFakeModeSwitchPress = 0; +static int sentFakeModeSwitchRelease = 0; +static int sentFakeLevel3ShiftPress = 0; +static int sentFakeLevel3ShiftRelease = 0; +static int sentFakeAltRRelease = 0; + +static int shmInitTrap = 0; + +Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display) +{ + logTrace("Poller::Poller"); + + display_ = NULL; + shadowDisplayName_ = input -> getShadowDisplayName(); + + tmpBuffer_ = NULL; + + xtestExtension_ = -1; + shmExtension_ = -1; + randrExtension_ = -1; + damageExtension_ = -1; + + shadowDisplayUid_ = -1; + + image_ = NULL; + + shminfo_ = NULL; +} + +Poller::~Poller() +{ + logTrace("Poller::~Poller"); + + if (shmExtension_ == 1) + { + XShmDetach(display_, shminfo_); + XDestroyImage(image_); + shmdt(shminfo_ -> shmaddr); + shmctl(shminfo_ -> shmid, IPC_RMID, 0); + } + + if (shminfo_ != NULL) + { + delete shminfo_; + + shminfo_ = NULL; + } + + if (display_ != NULL) + { + XCloseDisplay(display_); + } + + if (tmpBuffer_ != NULL && shmExtension_ != -1 && damageExtension_ == 1) + { + XFree(tmpBuffer_); + + tmpBuffer_ = NULL; + } +} + +int Poller::init() +{ + logTrace("Poller::init"); + + if (display_ == NULL) + { + display_ = XOpenDisplay(shadowDisplayName_); + + setShadowDisplay(display_); + } + + logTest("Poller::init:" ,"Shadow display [%p] name [%s].", (Display *) display_, shadowDisplayName_); + + if (display_ == NULL) + { + logTest("Poller::init", "Failed to connect to display [%s].", shadowDisplayName_ ? shadowDisplayName_ : ""); + + return -1; + } + + setRootSize(); + + logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].", + width_, height_, depth_, bpl_, bpp_); + + xtestInit(); + + shmInit(); + + randrInit(); + + damageInit(); + + return CorePoller::init(); +} + +int Poller::updateShadowFrameBuffer(void) +{ + if (shmExtension_ == 1) + { + if (XShmGetImage(display_, DefaultRootWindow(display_), image_, 0, 0, AllPlanes) == 0) + { + logDebug("Poller::updateShadowFrameBuffer", "XShmGetImage failed!"); + + return -1; + } + } + else + { + image_ = XGetImage(display_, DefaultRootWindow(display_), 0, 0, width_, + height_, AllPlanes, ZPixmap); + + if (image_ == NULL) + { + logDebug("Poller::updateShadowFrameBuffer", "XGetImage failed!"); + + return -1; + } + } + + return 1; +} + +char *Poller::getRect(XRectangle r) +{ + logTrace("Poller::getRect"); + + logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].", + r.x, r.y, r.width, r.height); + + if (shmExtension_ == 1) + { + if (damageExtension_ == 1) + { + image_ -> width = r.width; + image_ -> height = r.height; + + image_ -> bytes_per_line = ROUNDUP((image_ -> bits_per_pixel * image_ -> width), image_ -> bitmap_pad); + + if (XShmGetImage(display_, DefaultRootWindow(display_), image_, r.x, r.y, AllPlanes) == 0) + { + logDebug("Poller::getRect", "XShmGetImage failed!"); + + return NULL; + } + + tmpBuffer_ = image_ -> data; + } + else + { + image_ -> width = r.width; + image_ -> height = r.height; + + image_ -> bytes_per_line = ROUNDUP((image_ -> bits_per_pixel * image_ -> width), image_ -> bitmap_pad); + + if (XShmGetImage(display_, DefaultRootWindow(display_), image_, r.x, r.y, AllPlanes) == 0) + { + logDebug("Poller::getRect", "XShmGetImage failed!"); + } + + tmpBuffer_ = image_ -> data; + } + } + else + { + if (tmpBuffer_) + { + XFree(tmpBuffer_); + tmpBuffer_ = NULL; + } + + image_ = XGetImage(display_, DefaultRootWindow(display_), r.x, r.y, r.width, r.height, AllPlanes, ZPixmap); + + if (image_ == NULL) + { + logError("Poller::getRect", ESET(ENOMSG)); + + return NULL; + } + + tmpBuffer_ = image_ -> data; + + if (image_ -> obdata) + { + XFree(image_ -> obdata); + } + + XFree(image_); + + image_ = NULL; + } + + return tmpBuffer_; +} + +void Poller::shmInit(void) +{ + int major, minor; + int pixmaps; + + logTest("Poller::shmInit", "Added shmExtension_ [%d].", shmExtension_); + + if (shmExtension_ >= 0) + { + logDebug("Poller::shmInit", "Called with shared memory already initialized."); + + if (shmInitTrap == 0) + { + return; + } + } + + if (shmExtension_ < 0 && NXShadowOptions.optionShmExtension == 0) + { + shmExtension_ = 0; + + logUser("Poller::shmInit: Disabling use of MIT-SHM extension.\n"); + + return; + } + + if (XShmQueryVersion(display_, &major, &minor, &pixmaps) == 0) + { + logDebug("Poller::shmInit", "MIT_SHM: Shared memory extension not available."); + + shmExtension_ = 0; + } + else + { + logDebug("Poller::shmInit", "MIT_SHM: Shared memory extension available."); + + if (shminfo_ != NULL) + { + destroyShmImage(); + } + + shminfo_ = (XShmSegmentInfo* ) new XShmSegmentInfo; + + if (shminfo_ == NULL) + { + logError("Poller::shmInit", ESET(ENOMEM)); + + shmExtension_ = 0; + + return; + } + + image_ = (XImage *)XShmCreateImage(display_, display_ -> screens[0].root_visual, depth_, ZPixmap, + NULL, shminfo_, width_, height_); + + if (image_ == NULL) + { + logError("Poller::shmInit", ESET(ENOMSG)); + + shmExtension_ = 0; + + return; + } + + shadowDisplayUid_ = NXShadowOptions.optionShadowDisplayUid; + + logDebug("Poller::shmInit", "Master X server uid [%d].", NXShadowOptions.optionShadowDisplayUid); + + shminfo_ -> shmid = shmget(IPC_PRIVATE, image_ -> bytes_per_line * image_ -> height, IPC_CREAT | 0666); + + if (shminfo_ -> shmid < 0) + { + logDebug("Poller::shmInit", "kernel id error."); + + shmExtension_ = 0; + + return; + } + + logDebug("Poller::shmInit", "Created shm segment with shmid [%d].", shminfo_ -> shmid); + + shminfo_ -> shmaddr = (char *)shmat(shminfo_ -> shmid, 0, 0); + + if (shminfo_ -> shmaddr < 0) + { + logWarning("Poller::shmInit", "Couldn't attach to shm segment."); + } + + logDebug("Poller::shmInit", "shminfo_ -> shmaddr [%p].", shminfo_ -> shmaddr); + + image_ -> data = shminfo_ -> shmaddr; + + shminfo_ -> readOnly = 0; + + if (XShmAttach(display_, shminfo_) == 0) + { + logDebug("Poller::shmInit", "XShmAttach failed."); + + shmExtension_ = 0; + + return; + } + + // + // Mark the shm segment to be destroyed after + // the last process detach. Let the X server + // complete the X_ShmAttach request, before. + // + + XSync(display_, 0); + + struct shmid_ds ds; + + shmctl(shminfo_ -> shmid, IPC_STAT, &ds); + + if (shadowDisplayUid_ != -1) + { + ds.shm_perm.uid = (ushort) shadowDisplayUid_; + } + else + { + logWarning("Poller::shmInit", "Couldn't set uid for shm segment."); + } + + ds.shm_perm.mode = 0600; + + shmctl(shminfo_ -> shmid, IPC_SET, &ds); + + shmctl(shminfo_ -> shmid, IPC_STAT, &ds); + + shmctl(shminfo_ -> shmid, IPC_RMID, 0); + + logDebug("Poller::shmInit", "Number of attaches to shm segment [%d] are [%d].\n", + shminfo_ -> shmid, (int) ds.shm_nattch); + + if (ds.shm_nattch > 2) + { + logWarning("Poller::shmInit", "More than two attaches to the shm segment."); + + destroyShmImage(); + + shmExtension_ = 0; + + return; + } + + shmExtension_ = 1; + } +} + +void Poller::keymapShadowInit(Display *display) +{ + int i, len; + CARD32 *map; + + if (NXShadowKeymap != NULL) + { + shadowMinKey = NXShadowKeymap -> minKeyCode; + shadowMaxKey = NXShadowKeymap -> maxKeyCode; + shadowMapWidth = NXShadowKeymap -> mapWidth; + + len = (shadowMaxKey - shadowMinKey + 1) * shadowMapWidth; + + map = (CARD32 *) NXShadowKeymap -> map; + + if (shadowKeymap != NULL) + { + free(shadowKeymap); + } + + shadowKeymap = (KeySym *) malloc(len * sizeof(KeySym)); + + if (shadowKeymap != NULL) + { + for (i = 0; i < len; i++) + { + shadowKeymap[i] = map[i]; + } + + shadowKeysyms = shadowKeymap; + } + } + + if (shadowKeysyms == NULL) + { + XDisplayKeycodes(display, &shadowMinKey, &shadowMaxKey); + + shadowKeysyms = XGetKeyboardMapping(display, shadowMinKey, shadowMaxKey - shadowMinKey + 1, + &shadowMapWidth); + } + + #ifdef DEBUG + if (shadowKeysyms != NULL) + { + for (i = 0; i < (shadowMaxKey - shadowMinKey + 1) * shadowMapWidth; i++) + { + if (i % shadowMapWidth == 0) + { + logDebug("Poller::keymapShadowInit", "keycode [%d]", (int) (i / shadowMapWidth)); + } + + logDebug("\tkeysym", " [%x] [%s]", (unsigned int) shadowKeysyms[i], XKeysymToString(shadowKeysyms[i])); + } + } + #endif +} + +void Poller::keymapMasterInit() +{ + XDisplayKeycodes(display_, &masterMinKey, &masterMaxKey); + + masterKeysyms = XGetKeyboardMapping(display_, masterMinKey, masterMaxKey - masterMinKey + 1, + &masterMapWidth); + + #ifdef DEBUG + if (masterKeysyms != NULL) + { + for (int i = 0; i < (masterMaxKey - masterMinKey + 1) * masterMapWidth; i++) + { + if (i % masterMapWidth == 0) + { + logDebug("Poller::keymapMasterInit", "keycode [%d]", (int) (i / masterMapWidth)); + } + + logDebug("\tkeysym", " [%x] [%s]", (unsigned int) masterKeysyms[i], XKeysymToString(masterKeysyms[i])); + } + } + #endif +} + +KeySym Poller::keymapKeycodeToKeysym(KeyCode keycode, KeySym *keysyms, + int minKey, int mapWidth, int col) +{ + int index = ((keycode - minKey) * mapWidth) + col; + return keysyms[index]; +} + +KeyCode Poller::keymapKeysymToKeycode(KeySym keysym, KeySym *keysyms, + int minKey, int maxKey, int mapWidth, int *col) +{ + for (int i = 0; i < (maxKey - minKey + 1) * mapWidth; i++) + { + if (keysyms[i] == keysym) + { + *col = i % mapWidth; + return i / mapWidth + minKey; + } + } + return 0; +} + +KeyCode Poller::translateKeysymToKeycode(KeySym keysym, int *col) +{ + KeyCode keycode; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + + if (keycode == 0) + { + if (((keysym >> 8) == 0) && (keysym >= XK_a) && (keysym <= XK_z)) + { + /* + * The master session has a Solaris keyboard. + */ + + keysym -= XK_a - XK_A; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + } + else if (keysym == XK_Shift_R) + { + keysym = XK_Shift_L; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + } + else if (keysym == XK_Shift_L) + { + keysym = XK_Shift_R; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + } + else if (keysym == XK_ISO_Level3_Shift) + { + keysym = XK_Mode_switch; + + if ((keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col)) == 0) + { + keysym = XK_Alt_R; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + } + } + else if (keysym == XK_Alt_R) + { + keysym = XK_ISO_Level3_Shift; + + if ((keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col)) == 0) + { + keysym = XK_Mode_switch; + + keycode = keymapKeysymToKeycode(keysym, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, col); + } + } + } + return keycode; +} + +Bool Poller::checkModifierKeys(KeySym keysym, Bool isKeyPress) +{ + switch (keysym) + { + case XK_Shift_L: + leftShiftOn = isKeyPress; + return True; + case XK_Shift_R: + rightShiftOn = isKeyPress; + return True; + case XK_Mode_switch: + modeSwitchOn = isKeyPress; + return True; + case XK_ISO_Level3_Shift: + level3ShiftOn = isKeyPress; + return True; + case XK_Alt_R: + altROn = isKeyPress; + return True; + default: + return False; + } +} + +void Poller::sendFakeModifierEvents(int pos, Bool skip) +{ + KeySym fakeKeysym; + int col; + + if ((!leftShiftOn && !rightShiftOn) && + (!modeSwitchOn && !level3ShiftOn && !altROn)) + { + if (pos == 1 || pos == 3) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + sentFakeLShiftPress = 1; + } + if (pos == 2 || pos == 3) + { + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + + if (fakeKeysym == 0) + { + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + sentFakeModeSwitchPress = 1; + } + else + { + sentFakeLevel3ShiftPress = 1; + } + + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + } + } + + else if ((leftShiftOn || rightShiftOn) && + (!modeSwitchOn && !level3ShiftOn && !altROn)) + { + if ((pos == 0 && !skip) || pos == 2) + { + if (leftShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeLShiftRelease = 1; + } + if (rightShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeRShiftRelease = 1; + } + } + if (pos == 2 || pos ==3) + { + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + + if (fakeKeysym == 0) + { + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + sentFakeModeSwitchPress = 1; + } + else + { + sentFakeLevel3ShiftPress = 1; + } + + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + } + } + + else if ((!leftShiftOn && !rightShiftOn) && + (modeSwitchOn || level3ShiftOn || altROn)) + { + if (pos == 1 || pos == 3) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + sentFakeLShiftPress = 1; + } + if (pos == 0 || pos == 1) + { + if (modeSwitchOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeModeSwitchRelease = 1; + } + if (level3ShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeLevel3ShiftRelease = 1; + } + if (altROn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeAltRRelease = 1; + } + } + } + + else if ((leftShiftOn || rightShiftOn) && + (modeSwitchOn || level3ShiftOn || altROn)) + { + if (pos == 0 || pos == 2) + { + if (leftShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeLShiftRelease = 1; + } + if (rightShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeRShiftRelease = 1; + } + } + if (pos == 0 || pos == 1) + { + if (modeSwitchOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeModeSwitchRelease = 1; + } + if (level3ShiftOn) + { + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeLevel3ShiftRelease = 1; + } + if (altROn) + { + fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + sentFakeAltRRelease = 1; + } + } + } +} + +void Poller::cancelFakeModifierEvents() +{ + KeySym fakeKeysym; + int col; + + if (sentFakeLShiftPress) + { + logTest("Poller::handleKeyboardEvent", "Fake Shift_L key press event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake Shift_L key release event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + + sentFakeLShiftPress = 0; + } + + if (sentFakeLShiftRelease) + { + logTest("Poller::handleKeyboardEvent", "Fake Shift_L key release event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake Shift_L key press event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Shift_L, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + + sentFakeLShiftRelease = 0; + } + + if (sentFakeRShiftRelease) + { + logTest("Poller::handleKeyboardEvent", "Fake Shift_R key release event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake Shift_R key press event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Shift_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + + sentFakeRShiftRelease = 0; + } + + if (sentFakeModeSwitchPress) + { + logTest("Poller::handleKeyboardEvent", "Fake Mode_switch key press event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake Mode_switch key release event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + + sentFakeModeSwitchPress = 0; + } + + if (sentFakeModeSwitchRelease) + { + logTest("Poller::handleKeyboardEvent", "Fake Mode_switch key release event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending Mode_switch key press event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Mode_switch, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + + sentFakeModeSwitchRelease = 0; + } + + if (sentFakeLevel3ShiftPress) + { + logTest("Poller::handleKeyboardEvent", "Fake ISO_Level3_Shift key press event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake ISO_Level3_Shift key release event"); + + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 0, 0); + + sentFakeLevel3ShiftPress = 0; + } + + if (sentFakeLevel3ShiftRelease) + { + logTest("Poller::handleKeyboardEvent", "Fake ISO_Level3_Shift key release event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake ISO_Level3_Shift key press event"); + + fakeKeysym = keymapKeysymToKeycode(XK_ISO_Level3_Shift, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + + sentFakeLevel3ShiftRelease = 0; + } + + if (sentFakeAltRRelease) + { + logTest("Poller::handleKeyboardEvent", "Fake XK_Alt_R key release event has been sent"); + logTest("Poller::handleKeyboardEvent", "Sending fake XK_Alt_R key press event"); + + fakeKeysym = keymapKeysymToKeycode(XK_Alt_R, masterKeysyms, masterMinKey, + masterMaxKey, masterMapWidth, &col); + XTestFakeKeyEvent(display_, fakeKeysym, 1, 0); + + sentFakeAltRRelease = 0; + } +} + +Bool Poller::keyIsDown(KeyCode keycode) +{ + KeyPressedRec *downKey; + + downKey = shadowKeyPressedPtr; + + while (downKey) + { + if (downKey -> keyRcvd == keycode) + { + return True; + } + downKey = downKey -> next; + } + + return False; +} + +void Poller::addKeyPressed(KeyCode received, KeyCode sent) +{ + KeyPressedRec *downKey; + + if (!keyIsDown(received)) + { + if (shadowKeyPressedPtr == NULL) + { + shadowKeyPressedPtr = (KeyPressedRec *) malloc(sizeof(KeyPressedRec)); + + shadowKeyPressedPtr -> keyRcvd = received; + shadowKeyPressedPtr -> keySent = sent; + shadowKeyPressedPtr -> next = NULL; + } + else + { + downKey = shadowKeyPressedPtr; + + while (downKey -> next != NULL) + { + downKey = downKey -> next; + } + + downKey -> next = (KeyPressedRec *) malloc(sizeof(KeyPressedRec)); + + downKey -> next -> keyRcvd = received; + downKey -> next -> keySent = sent; + downKey -> next -> next = NULL; + } + } +} + +KeyCode Poller::getKeyPressed(KeyCode received) +{ + KeyCode sent; + KeyPressedRec *downKey; + KeyPressedRec *tempKey; + + if (shadowKeyPressedPtr != NULL) + { + if (shadowKeyPressedPtr -> keyRcvd == received) + { + sent = shadowKeyPressedPtr -> keySent; + + tempKey = shadowKeyPressedPtr; + shadowKeyPressedPtr = shadowKeyPressedPtr -> next; + free(tempKey); + + return sent; + } + else + { + downKey = shadowKeyPressedPtr; + + while (downKey -> next != NULL) + { + if (downKey -> next -> keyRcvd == received) + { + sent = downKey -> next -> keySent; + + tempKey = downKey -> next; + downKey -> next = downKey -> next -> next; + free(tempKey); + + return sent; + } + else + { + downKey = downKey -> next; + } + } + } + } + return 0; +} + +void Poller::handleKeyboardEvent(Display *display, XEvent *event) +{ + if (xtestExtension_ == 0 || display_ == 0) + { + return; + } + + logTest("Poller::handleKeyboardEvent", "Handling event at [%p]", event); + +#ifdef TRANSLATE_ALWAYS + + KeyCode keycode; + KeySym keysym; + + int col = 0; + + Bool isKeyPress = False; + Bool isModifier = False; + Bool isShiftComb = False; + Bool skip = False; + + if (event -> type == KeyPress) + { + isKeyPress = True; + } + + if (shadowKeysyms == NULL) + { + keymapShadowInit(event -> xkey.display); + } + + if (masterKeysyms == NULL) + { + keymapMasterInit(); + } + + if (shadowKeysyms == NULL || masterKeysyms == NULL) + { + logTest("Poller::handleKeyboardEvent", "Unable to initialize keymaps. Do not translate"); + + keycode = event -> xkey.keycode; + + goto SendKeycode; + } + + keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, + shadowMinKey, shadowMapWidth, 0); + + isModifier = checkModifierKeys(keysym, isKeyPress); + + if (event -> type == KeyRelease) + { + KeyCode keycodeToSend; + + keycodeToSend = getKeyPressed(event -> xkey.keycode); + + if (keycodeToSend) + { + keycode = keycodeToSend; + + goto SendKeycode; + } + } + + /* + * Convert case for Solaris keyboard. + */ + + if (((keysym >> 8) == 0) && (keysym >= XK_A) && (keysym <= XK_Z)) + { + if (!leftShiftOn && !rightShiftOn) + { + keysym += XK_a - XK_A; + } + else + { + skip = True; + } + } + + if (!isModifier) + { + if ((leftShiftOn || rightShiftOn) && + (!modeSwitchOn && !level3ShiftOn && !altROn) && + !skip) + { + KeySym tempKeysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, + shadowMinKey, shadowMapWidth, 1); + + if (tempKeysym == 0) + { + isShiftComb = True; + } + else + { + keysym = tempKeysym; + } + } + else if ((!leftShiftOn && !rightShiftOn) && + (modeSwitchOn || level3ShiftOn || altROn)) + { + keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, + shadowMinKey, shadowMapWidth, 2); + } + else if ((leftShiftOn || rightShiftOn) && + (modeSwitchOn || level3ShiftOn || altROn)) + { + keysym = keymapKeycodeToKeysym(event -> xkey.keycode, shadowKeysyms, + shadowMinKey, shadowMapWidth, 3); + } + } + + if (keysym == 0) + { + logTest("Poller::handleKeyboardEvent", "Null keysym. Return"); + + return; + } + + logTest("Poller::handleKeyboardEvent", "keysym [%x] [%s]", + (unsigned int)keysym, XKeysymToString(keysym)); + + if (keysym == XK_Mode_switch) + { + keysym = XK_ISO_Level3_Shift; + } + + keycode = translateKeysymToKeycode(keysym, &col); + + if (keycode == 0) + { + logTest("Poller::handleKeyboardEvent", "No keycode found for keysym [%x] [%s]. Return", + (unsigned int)keysym, XKeysymToString(keysym)); + return; + } + + logTest("Poller::handleKeyboardEvent", "keycode [%d] translated into keycode [%d]", + (int)event -> xkey.keycode, (unsigned int)keycode); + + if (event -> type == KeyPress) + { + addKeyPressed(event -> xkey.keycode, keycode); + } + + /* + * Send fake modifier events. + */ + + if (!isModifier && isShiftComb == False) + { + sendFakeModifierEvents(col, ((keysym >> 8) == 0) && (keysym >= XK_A) && (keysym <= XK_Z)); + } + +SendKeycode: + + /* + * Send the event. + */ + + XTestFakeKeyEvent(display_, keycode, isKeyPress, 0); + + /* + * Check if fake modifier events have been sent. + */ + + cancelFakeModifierEvents(); + +#else // TRANSLATE_ALWAYS + + // + // Use keysyms to translate keycodes across different + // keyboard models. Unuseful when both keyboards have + // same keycodes (e.g. both are pc keyboards). + // + + #ifdef TRANSLATE_KEYCODES + + KeyCode keycode = XKeysymToKeycode(display_, XK_A); + + if (XKeysymToKeycode(event -> xkey.display, XK_A) != keycode) + { + KeySym keysym = XKeycodeToKeysym(event -> xkey.display, event -> xkey.keycode, 0); + + if (keysym == XK_Mode_switch || keysym == XK_ISO_Level3_Shift) + { + logUser("Poller::handleKeyboardEvent: keysym [%x].\n", (unsigned int)keysym); + + if (XKeycodeToKeysym(display_, 113, 0) == XK_ISO_Level3_Shift || + (XKeycodeToKeysym(display_, 124, 0) == XK_ISO_Level3_Shift)) + { + event -> xkey.keycode = 113; + } + else + { + event -> xkey.keycode = XKeysymToKeycode(display_, XK_Mode_switch); + } + + logUser("Poller::handleKeyboardEvent: keycode translated to [%x].\n", (unsigned int)event -> xkey.keycode); + } + else + { + event -> xkey.keycode = XKeysymToKeycode(display_, keysym); + } + } + + #endif // TRANSLATE_KEYCODES + + if (event -> type == KeyPress) + { + XTestFakeKeyEvent(display_, event -> xkey.keycode, 1, 0); + } + else if (event -> type == KeyRelease) + { + XTestFakeKeyEvent(display_, event -> xkey.keycode, 0, 0); + } + +#endif // TRANSLATE_ALWAYS +} + +void Poller::handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress) +{ + KeyCode keycode; + int col; + + if (masterKeysyms == NULL) + { + keymapMasterInit(); + } + + if (masterKeysyms == NULL) + { + logTest("Poller::handleWebKeyboardEvent", "Unable to initialize keymap"); + + return; + } + + keycode = translateKeysymToKeycode(keysym, &col); + + if (keycode == 0) + { + logTest("Poller::handleKeyboardEvent", "No keycode found for keysym [%x] [%s]. Return", + (unsigned int)keysym, XKeysymToString(keysym)); + return; + } + + logTest("Poller::handleKeyboardEvent", "keysym [%x] [%s] translated into keycode [%x]", + (unsigned int)keysym, XKeysymToString(keysym), (unsigned int)keycode); + + /* + * Send fake modifier events. + */ + + if (!checkModifierKeys(keysym, isKeyPress)) + { + sendFakeModifierEvents(col, False); + } + + /* + * Send the event. + */ + + XTestFakeKeyEvent(display_, keycode, isKeyPress, 0); + + /* + * Check if fake modifier events have been sent. + */ + + cancelFakeModifierEvents(); + +} + +void Poller::handleMouseEvent(Display *display, XEvent *event) +{ + if (xtestExtension_ == 0 || display_ == 0) + { + return; + } + + if (event -> type == MotionNotify) + { + XTestFakeMotionEvent(display_, 0, event -> xmotion.x, event -> xmotion.y, 0); + } + else if (event -> type == ButtonPress) + { + XTestFakeButtonEvent(display_, event -> xbutton.button, True, 0); + } + else if (event -> type == ButtonRelease) + { + XTestFakeButtonEvent(display_, event -> xbutton.button, False, 0); + } + + XFlush(display_); +} + +void Poller::setRootSize(void) +{ + width_ = WidthOfScreen(DefaultScreenOfDisplay(display_)); + height_ = HeightOfScreen(DefaultScreenOfDisplay(display_)); + depth_ = DefaultDepth(display_, DefaultScreen(display_)); + + if (depth_ == 8) bpp_ = 1; + else if (depth_ == 16) bpp_ = 2; + else bpp_ = 4; + + bpl_ = width_ * bpp_; +} + +void Poller::destroyShmImage(void) +{ + XShmDetach(display_, shminfo_); + XDestroyImage(image_); + image_ = NULL; + + shmdt(shminfo_ -> shmaddr); + shmctl(shminfo_ -> shmid, IPC_RMID, 0); + + delete shminfo_; + shminfo_ = NULL; +} + +void Poller::xtestInit(void) +{ + int eventBase; + int errorBase; + int versionMajor; + int versionMinor; + int result; + + xtestExtension_ = 0; + + result = XTestQueryExtension(display_, &eventBase, &errorBase, &versionMajor, &versionMinor); + + if (result == 0) + { + xtestExtension_ = 0; + + logWarning("Poller::xtestInit", "Failed while querying for XTEST extension."); + } + else + { + logDebug("Poller::xtestInit", "XTEST version %d.%d.", versionMajor, versionMinor); + + xtestExtension_ = 1; + } + + // + // Make this client impervious to grabs. + // + + if (xtestExtension_ == 1) + { + XTestGrabControl(display_, 1); + } +} + +void Poller::randrInit(void) +{ + int randrEventBase; + int randrErrorBase; + + if (XRRQueryExtension(display_, &randrEventBase, &randrErrorBase) == 0) + { + logWarning("Poller::randrInit", "Randr extension not supported on this " + "display."); + + randrExtension_ = 0; + + return; + } + + XRRSelectInput(display_, DefaultRootWindow(display_), + RRScreenChangeNotifyMask); + + randrEventBase_ = randrEventBase; + + randrExtension_ = 1; + + return; +} + +void Poller::damageInit(void) +{ + int damageMajorVersion = 0; + int damageMinorVersion = 0; + + int damageEventBase = 0; + int damageErrorBase = 0; + + if (damageExtension_ >= 0) + { + logDebug("Poller::damageInit", "Called with damage already initialized."); + } + + if (damageExtension_ == 0) + { + logDebug("Poller::damageInit", "Damage disabled. Skip initialization."); + + return; + } + + if (damageExtension_ < 0 && NXShadowOptions.optionDamageExtension == 0) + { + damageExtension_ = 0; + + logUser("Poller::damageInit: Disabling use of DAMAGE extension.\n"); + + return; + } + + damageExtension_ = 0; + + mirrorChanges_ = 0; + + if (XDamageQueryExtension(display_, &damageEventBase, &damageErrorBase) == 0) + { + logUser("Poller::damageInit: DAMAGE not supported.\n"); + + return; + } + #ifdef DEBUG + else + { + fprintf(stderr, "Poller::damageInit: DAMAGE supported. " + "Event base [%d] error base [%d].\n", damageEventBase, damageErrorBase); + } + #endif + + damageEventBase_ = damageEventBase; + + if (XDamageQueryVersion(display_, &damageMajorVersion, &damageMinorVersion) == 0) + { + logWarning("Poller::damageInit", "Error on querying DAMAGE version.\n"); + + damageExtension_ = 0; + + return; + } + #ifdef DEBUG + else + { + fprintf(stderr, "Poller::damageInit: DAMAGE version %d.%d.\n", + damageMajorVersion, damageMinorVersion); + } + #endif + + damage_ = XDamageCreate(display_, DefaultRootWindow(display_), XDamageReportRawRectangles); + + damageExtension_= 1; + + mirror_ = 1; + + return; +} + +void Poller::getEvents(void) +{ + XEvent X; + + if (damageExtension_ == 1) + { + XDamageSubtract(display_, damage_, None, None); + } + + XSync(display_, 0); + + while (XCheckIfEvent(display_, &X, anyEventPredicate, NULL) == 1) + { + if (randrExtension_ == 1 && (X.type == randrEventBase_ + RRScreenChangeNotify || X.type == ConfigureNotify)) + { + XRRUpdateConfiguration(&X); + + handleRRScreenChangeNotify(&X); + + continue; + } + + if (damageExtension_ == 1 && X.type == damageEventBase_ + XDamageNotify) + { + handleDamageNotify(&X); + } + } + + if (damageExtension_ == 1) + { + updateDamagedAreas(); + } + + XFlush(display_); +} + +void Poller::handleRRScreenChangeNotify(XEvent *X) +{ + return; +} + +void Poller::handleDamageNotify(XEvent *X) +{ + XDamageNotifyEvent *e = (XDamageNotifyEvent *) X; + + // + // e->drawable is the window ID of the damaged window + // e->geometry is the geometry of the damaged window + // e->area is the bounding rect for the damaged area + // e->damage is the damage handle returned by XDamageCreate() + // + + #ifdef DEBUG + fprintf(stderr, "handleDamageNotify: drawable [%d] damage [%d] geometry [%d][%d][%d][%d] area [%d][%d][%d][%d].\n", + (int) e -> drawable, (int) e -> damage, e -> geometry.x, e -> geometry.y, + e -> geometry.width, e -> geometry.height, e -> area.x, e -> area.y, + e -> area.width, e -> area.height); + #endif + + XRectangle rectangle = {e -> area.x, e -> area.y, e -> area.width, e -> area.height}; + + XUnionRectWithRegion(&rectangle, lastUpdatedRegion_, lastUpdatedRegion_); + + mirrorChanges_ = 1; + + return; +} + +void Poller::updateDamagedAreas(void) +{ + BOX *boxPtr; + + XRectangle rectangle; + + int i; + int y; + + for (i = 0; i < lastUpdatedRegion_ -> numRects; i++) + { + boxPtr = lastUpdatedRegion_ -> rects + i; + + if (shmExtension_ == 1) + { + image_ -> width = boxPtr -> x2 - boxPtr -> x1; + image_ -> height = boxPtr -> y2 - boxPtr -> y1; + image_ -> bytes_per_line = + ROUNDUP((image_ -> bits_per_pixel * image_ -> width), + image_ -> bitmap_pad); + + if (XShmGetImage(display_, DefaultRootWindow(display_), image_, + boxPtr -> x1, boxPtr -> y1, AllPlanes) == 0) + { + logDebug("Poller::updateDamagedAreas", "XShmGetImage failed!"); + + return; + } + } + else if (shmExtension_ == 0) + { + image_ = XGetImage(display_, DefaultRootWindow(display_), boxPtr -> x1, + boxPtr -> y1, boxPtr -> x2 - boxPtr -> x1, + boxPtr -> y2 - boxPtr -> y1, AllPlanes, + ZPixmap); + + if (image_ == NULL) + { + logDebug("Poller::updateDamagedAreas", "XGetImage failed!"); + + return; + } + + image_ -> width = boxPtr -> x2 - boxPtr -> x1; + image_ -> height = boxPtr -> y2 - boxPtr -> y1; + image_ -> bytes_per_line = + ROUNDUP((image_ -> bits_per_pixel * image_ -> width), + image_ -> bitmap_pad); + } + + rectangle.height = 1; + rectangle.width = image_ -> width; + rectangle.x = boxPtr -> x1; + rectangle.y = boxPtr -> y1; + + for (y = 0; y < image_ -> height; y++) + { + update(image_ -> data + y * image_ -> bytes_per_line, rectangle); + + rectangle.y++; + } + + if (shmExtension_ != 1) + { + XDestroyImage(image_); + + image_ = NULL; + } + } + + return; +} + +void Poller::getScreenSize(int *w, int *h) +{ + *w = WidthOfScreen(DefaultScreenOfDisplay(display_)); + *h = HeightOfScreen(DefaultScreenOfDisplay(display_)); +} + +void Poller::setScreenSize(int *w, int *h) +{ + setRootSize(); + + shmInitTrap = 1; + shmInit(); + shmInitTrap = 0; + + *w = width_; + *h = height_; + + logDebug("Poller::setScreenSize", "New size of screen [%d, %d]", width_, height_); +} + +int anyEventPredicate(Display *display, XEvent *event, XPointer parameter) +{ + return 1; +} + +#endif /* !defined(__CYGWIN32__) && !defined(WIN32) */ diff --git a/nxcompshad/src/X11.h b/nxcompshad/src/X11.h new file mode 100644 index 000000000..87dd31fea --- /dev/null +++ b/nxcompshad/src/X11.h @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */ +/* Copyright (c) 2008-2014 Oleksandr Shneyder */ +/* Copyright (c) 2014-2016 Ulrich Sibiller */ +/* Copyright (c) 2014-2016 Mihai Moldovan */ +/* Copyright (c) 2011-2016 Mike Gabriel */ +/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */ +/* */ +/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */ +/* are copyright of the aforementioned persons and companies. */ +/* */ +/* Redistribution and use of the present software is allowed according */ +/* to terms specified in the file LICENSE which comes in the source */ +/* distribution. */ +/* */ +/* All rights reserved. */ +/* */ +/* NOTE: This software has received contributions from various other */ +/* contributors, only the core maintainers and supporters are listed as */ +/* copyright holders. Please contact us, if you feel you should be listed */ +/* as copyright holder, as well. */ +/* */ +/**************************************************************************/ + +#ifndef X11Poller_H +#define X11Poller_H + +#include +#include +#include "X11/include/Xdamage_nxcompshad.h" +#include "X11/include/Xrandr_nxcompshad.h" + +#include "Core.h" + +class Poller : public CorePoller +{ + public: + + Poller(Input *, Display *display, int = 0); + + ~Poller(); + + int init(); + + void setRootSize(); + + void destroyShmImage(); + + void getEvents(void); + + void getScreenSize(int *width, int *height); + + void setScreenSize(int *width, int *height); + + private: + + Display *display_; + + char *shadowDisplayName_; + + int shadowDisplayUid_; + + char *tmpBuffer_; + + char xtestExtension_; + + char shmExtension_; + + char randrExtension_; + + int randrEventBase_; + + char damageExtension_; + + int damageEventBase_; + + Damage damage_; + + Region repair_; + + char damageChanges_; + + XShmSegmentInfo *shminfo_; + + XImage *image_; + + int updateShadowFrameBuffer(void); + + char *getRect(XRectangle); + + void keymapShadowInit(Display *display); + + void keymapMasterInit(); + + KeySym keymapKeycodeToKeysym(KeyCode keycode, KeySym *keysyms, + int minKey, int per, int col); + + KeyCode keymapKeysymToKeycode(KeySym keysym, KeySym *keysyms, + int minKey, int maxKey, int per, int *col); + + KeyCode translateKeysymToKeycode(KeySym keysym, int *col); + + Bool checkModifierKeys(KeySym keysym, Bool isKeyPress); + + void sendFakeModifierEvents(int pos, Bool skip); + + void cancelFakeModifierEvents(); + + Bool keyIsDown(KeyCode keycode); + + void addKeyPressed(KeyCode received, KeyCode sent); + + KeyCode getKeyPressed(KeyCode received); + + void handleKeyboardEvent(Display *display, XEvent *); + + void handleWebKeyboardEvent(KeySym keysym, Bool isKeyPress); + + void handleMouseEvent(Display *, XEvent *); + + void xtestInit(void); + + void shmInit(void); + + void randrInit(void); + + void damageInit(void); + + void handleRRScreenChangeNotify(XEvent *); + + void handleDamageNotify(XEvent *); + + void updateDamagedAreas(void); +}; + +int anyEventPredicate(Display *display, XEvent *event, XPointer parameter); + +#endif /* X11Poller_H */ diff --git a/nxcompshad/src/X11/include/XTest_nxcompshad.h b/nxcompshad/src/X11/include/XTest_nxcompshad.h new file mode 100644 index 000000000..91a2ba40b --- /dev/null +++ b/nxcompshad/src/X11/include/XTest_nxcompshad.h @@ -0,0 +1,71 @@ +/* + +Copyright 1992, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +#ifndef _XTEST_H_ +#define _XTEST_H_ + +#include + +_XFUNCPROTOBEGIN + +Bool XTestQueryExtension( + Display* /* dpy */, + int* /* event_basep */, + int* /* error_basep */, + int* /* majorp */, + int* /* minorp */ +); + +extern int XTestFakeKeyEvent( + Display* /* dpy */, + unsigned int /* keycode */, + Bool /* is_press */, + unsigned long /* delay */ +); + +extern int XTestFakeButtonEvent( + Display* /* dpy */, + unsigned int /* button */, + Bool /* is_press */, + unsigned long /* delay */ +); + +extern int XTestFakeMotionEvent( + Display* /* dpy */, + int /* screen */, + int /* x */, + int /* y */, + unsigned long /* delay */ +); + +extern int XTestGrabControl( + Display* /* dpy */, + Bool /* impervious */ +); + +_XFUNCPROTOEND + +#endif diff --git a/nxcompshad/src/X11/include/Xdamage_nxcompshad.h b/nxcompshad/src/X11/include/Xdamage_nxcompshad.h new file mode 100644 index 000000000..cae3e1c67 --- /dev/null +++ b/nxcompshad/src/X11/include/Xdamage_nxcompshad.h @@ -0,0 +1,92 @@ +/* + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This file is a reduced version of the header file of + * + * + * This copy of code has been introduced to allow a clear namespace + * separation between and header files. + * + * This version of the Xdamage library header file only contains symbols + * required by nxcompshad and strictly avoids indirectly including + * from an X11 library that is also shipped in nx-X11/lib/. + * + * When using instead for inclusion in + * nxcompshad, it will attempt pulling in the + * header which in turn will include . However, the headers of + * the same name from should be used instead. + * + * FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this + * hack can be removed. + * + * 2015/06/26, Mike Gabriel + */ + + +#ifndef _XDAMAGE_H_ +#define _XDAMAGE_H_ + +#include +#include + +/* from */ +typedef XID XserverRegion; + +#define XDAMAGE_1_1_INTERFACE + +typedef XID Damage; + +typedef struct { + int type; /* event base */ + unsigned long serial; + Bool send_event; + Display *display; + Drawable drawable; + Damage damage; + int level; + Bool more; /* more events will be delivered immediately */ + Time timestamp; + XRectangle area; + XRectangle geometry; +} XDamageNotifyEvent; + +_XFUNCPROTOBEGIN + +Bool XDamageQueryExtension (Display *dpy, + int *event_base_return, + int *error_base_return); + +Status XDamageQueryVersion (Display *dpy, + int *major_version_return, + int *minor_version_return); + +Damage +XDamageCreate (Display *dpy, Drawable drawable, int level); + +void +XDamageSubtract (Display *dpy, Damage damage, + XserverRegion repair, XserverRegion parts); + +_XFUNCPROTOEND + +#endif /* _XDAMAGE_H_ */ diff --git a/nxcompshad/src/X11/include/Xrandr_nxcompshad.h b/nxcompshad/src/X11/include/Xrandr_nxcompshad.h new file mode 100644 index 000000000..4feb01685 --- /dev/null +++ b/nxcompshad/src/X11/include/Xrandr_nxcompshad.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2000 Compaq Computer Corporation, Inc. + * Copyright © 2002 Hewlett-Packard Company, Inc. + * Copyright © 2006 Intel Corporation + * Copyright © 2008 Red Hat, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Author: Jim Gettys, HP Labs, Hewlett-Packard, Inc. + * Keith Packard, Intel Corporation + */ + +/* + * This file is a reduced version of the header file of + * + * + * This copy of code has been introduced to allow a clear namespace + * separation between and header files. + * + * This version of the Xrandr library header file only contains symbols + * required by nxcompshad and strictly avoids indirectly including + * from an X11 library that is also shipped in nx-X11/lib/. + * + * When using instead for inclusion in + * nxcompshad, it will attempt pulling in the + * header which in turn will include . However, the headers of + * the same name from should be used instead. + * + * FIXME: Once the nxagent Xserver starts using libXrender from X.Org, this + * hack can be removed. + * + * 2015/06/26, Mike Gabriel + */ + +#ifndef _XRANDR_H_ +#define _XRANDR_H_ + +/* from */ +#define RRScreenChangeNotify 0 +#define RRScreenChangeNotifyMask (1L << 0) + +#include + +_XFUNCPROTOBEGIN + +/* internal representation is private to the library */ +typedef struct _XRRScreenConfiguration XRRScreenConfiguration; + +Bool XRRQueryExtension (Display *dpy, + int *event_base_return, + int *error_base_return); + +void XRRSelectInput(Display *dpy, Window window, int mask); + + +/* + * intended to take RRScreenChangeNotify, or + * ConfigureNotify (on the root window) + * returns 1 if it is an event type it understands, 0 if not + */ +int XRRUpdateConfiguration(XEvent *event); +_XFUNCPROTOEND + +#endif /* _XRANDR_H_ */ -- cgit v1.2.3 From dba850070044697a84f1baaad8ad274cc7601cb3 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Fri, 30 Jun 2017 14:49:03 +0200 Subject: =?UTF-8?q?nxcompshad/src/Regions.h:=20Avoid=20warning:=20?= =?UTF-8?q?=E2=80=98typedef=E2=80=99=20was=20ignored=20in=20this=20declara?= =?UTF-8?q?tion.=20Drop=20typedef=20declaration=20from=20=5FXRegion=20stru?= =?UTF-8?q?ct.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nxcompshad/src/Regions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nxcompshad/src/Regions.h b/nxcompshad/src/Regions.h index 59fdcb46c..2bc24a39c 100644 --- a/nxcompshad/src/Regions.h +++ b/nxcompshad/src/Regions.h @@ -33,7 +33,7 @@ typedef struct { short x1, x2, y1, y2; } Box, BOX, BoxRec, *BoxPtr; -typedef struct _XRegion { +struct _XRegion { long size; long numRects; BOX *rects; -- cgit v1.2.3 From d7789746285f1d4c1bd7763058aff3a31e250b23 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Wed, 12 Jul 2017 22:23:07 +0200 Subject: nxcompshad/src/Core.cpp: Don't redeclare (and shadow) curLine. Use curWorkLine instead. --- nxcompshad/src/Core.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/nxcompshad/src/Core.cpp b/nxcompshad/src/Core.cpp index de5f9a897..2b2163ea1 100644 --- a/nxcompshad/src/Core.cpp +++ b/nxcompshad/src/Core.cpp @@ -421,64 +421,64 @@ int CorePoller::isChanged(int (*checkIfInputCallback)(void *), void *arg, int *s if (foundChanges) { - int start, last, curLine, left, right; + int start, last, curWorkLine, left, right; - for (curLine = 0; curLine < (int) height_; curLine++) + for (curWorkLine = 0; curWorkLine < (int) height_; curWorkLine++) { - if (lineStatus_[curLine] == LINE_HAS_CHANGED) + if (lineStatus_[curWorkLine] == LINE_HAS_CHANGED) { break; } } - start = curLine; - last = curLine; + start = curWorkLine; + last = curWorkLine; - left = lefts_[curLine]; - right = rights_[curLine]; - curLine++; + left = lefts_[curWorkLine]; + right = rights_[curWorkLine]; + curWorkLine++; while (1) { - for (; curLine < (int) height_; curLine++) + for (; curWorkLine < (int) height_; curWorkLine++) { - if (lineStatus_[curLine] == LINE_HAS_CHANGED) + if (lineStatus_[curWorkLine] == LINE_HAS_CHANGED) { break; } } - if (curLine == (int) height_) + if (curWorkLine == (int) height_) { break; } - if ((curLine - last > minSliceHeight_) || (last - start > maxSliceHeight_)) + if ((curWorkLine - last > minSliceHeight_) || (last - start > maxSliceHeight_)) { XRectangle rect = {left, start, right - left + 1, last - start + 1}; XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_); - start = curLine; - left = lefts_[curLine]; - right = rights_[curLine]; + start = curWorkLine; + left = lefts_[curWorkLine]; + right = rights_[curWorkLine]; } else { - if (lefts_[curLine] < left) + if (lefts_[curWorkLine] < left) { - left = lefts_[curLine]; + left = lefts_[curWorkLine]; } - if (rights_[curLine] > right) + if (rights_[curWorkLine] > right) { - right = rights_[curLine]; + right = rights_[curWorkLine]; } } - last = curLine; + last = curWorkLine; - curLine++; + curWorkLine++; } // -- cgit v1.2.3 From 36fe0330e70d6ab827c2c27e10bcbe0838c1888e Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Wed, 12 Jul 2017 22:26:05 +0200 Subject: nxcompshad/src/Shadow.cpp: Drop duplicate prototype for NXShadowRemoveAllUpdaters(). Already in Shadow.h. --- nxcompshad/src/Shadow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/nxcompshad/src/Shadow.cpp b/nxcompshad/src/Shadow.cpp index 3db5039ce..c928e6ffd 100644 --- a/nxcompshad/src/Shadow.cpp +++ b/nxcompshad/src/Shadow.cpp @@ -57,8 +57,6 @@ static UpdateManager *updateManager; static Poller *poller; static Input *input; -int NXShadowRemoveAllUpdaters(); - inline bool NXShadowNotInitialized() { // -- cgit v1.2.3 From 8f5ce18d4f152619387b10d9d05ea4ceccc42b3a Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Wed, 12 Jul 2017 22:26:38 +0200 Subject: nxcompshad: Prototype for NXShadowResetOptions() missing. Export it as public symbol via Shadow.h." --- nxcompshad/include/Shadow.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nxcompshad/include/Shadow.h b/nxcompshad/include/Shadow.h index e1c57c432..c59d91eeb 100644 --- a/nxcompshad/include/Shadow.h +++ b/nxcompshad/include/Shadow.h @@ -65,6 +65,8 @@ typedef struct _ShadowOptions extern ShadowOptions NXShadowOptions; +extern void NXShadowResetOptions(); + extern int NXShadowCreate(void *, char *, char *, void **); extern void NXShadowDestroy(void); -- cgit v1.2.3 From 59e829f3647005a6c93662adfbcea36e27a993d8 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Wed, 12 Jul 2017 22:34:11 +0200 Subject: nxcompshad: Rewrite Logger class methods to properly take advantage of the 'gnu_printf' format attribute. --- nxcompshad/src/Logger.cpp | 20 ++++++++++++++++---- nxcompshad/src/Logger.h | 8 ++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/nxcompshad/src/Logger.cpp b/nxcompshad/src/Logger.cpp index 9648509b8..2f3eab65c 100644 --- a/nxcompshad/src/Logger.cpp +++ b/nxcompshad/src/Logger.cpp @@ -41,11 +41,14 @@ Logger logger; -void Logger::user(const char *format, va_list arguments) +void Logger::user(const char *format, ...) { char string[1024]; + va_list arguments; + va_start(arguments, format); vsnprintf(string, 1024, format, arguments); + va_end(arguments); fprintf(stderr, "%s\n", string); } @@ -56,20 +59,26 @@ void Logger::error(const char *name, int error) name, error, strerror(error)); } -void Logger::warning(const char *name, const char *format, va_list arguments) +void Logger::warning(const char *name, const char *format, ...) { char string[1024]; + va_list arguments; + va_start(arguments, format); vsnprintf(string, 1024, format, arguments); + va_end(arguments); fprintf(stderr, "%s: WARNING! %s\n", name, string); } -void Logger::test(const char *name, const char *format, va_list arguments) +void Logger::test(const char *name, const char *format, ...) { char string[1024]; + va_list arguments; + va_start(arguments, format); vsnprintf(string, 1024, format, arguments); + va_end(arguments); fprintf(stderr, "%s: %s\n", name, string); } @@ -79,11 +88,14 @@ void Logger::trace(const char *name) fprintf(stderr, "%s\n", name); } -void Logger::debug(const char *name, const char *format, va_list arguments) +void Logger::debug(const char *name, const char *format, ...) { char string[1024]; + va_list arguments; + va_start(arguments, format); vsnprintf(string, 1024, format, arguments); + va_end(arguments); fprintf(stderr, "%s: %s\n", name, string); } diff --git a/nxcompshad/src/Logger.h b/nxcompshad/src/Logger.h index eba81f642..37b378cb2 100644 --- a/nxcompshad/src/Logger.h +++ b/nxcompshad/src/Logger.h @@ -43,17 +43,17 @@ class Logger { public: - void user(const char *format, va_list arguments); + void user(const char *format, ...) __attribute__((format(gnu_printf, 2, 3))); void error(const char *name, int error); - void warning(const char *name, const char *format, va_list arguments); + void warning(const char *name, const char *format, ...) __attribute__((format(gnu_printf, 3, 4))); - void test(const char *name, const char *format, va_list arguments); + void test(const char *name, const char *format, ...) __attribute__((format(gnu_printf, 3, 4))); void trace(const char *name); - void debug(const char *name, const char *format, va_list arguments); + void debug(const char *name, const char *format, ...) __attribute__((format(gnu_printf, 3, 4))); void dump(const char *name, const char *data, int size); }; -- cgit v1.2.3