New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

21
nxcompshad/.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
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/Makefile
src/Makefile.in

23
nxcompshad/Makefile.am Normal file
View File

@@ -0,0 +1,23 @@
SUBDIRS = src
pkgconfig_DATA = nxcompshad.pc
ACLOCAL_AMFLAGS = -I m4
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)

1
nxcompshad/VERSION Symbolic link
View File

@@ -0,0 +1 @@
../VERSION

71
nxcompshad/configure.ac Normal file
View File

@@ -0,0 +1,71 @@
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-bzip2])
# Initialize libtool
AC_PROG_LIBTOOL
# enable this to add the variable to the Makefiles
#AC_ARG_VAR(NX_VERSION_CUSTOM, [custom version string])
if test "x$NX_VERSION_CUSTOM" != x; then
AC_DEFINE_UNQUOTED([NX_VERSION_CUSTOM], ["${NX_VERSION_CUSTOM}"], [user provided custom version string])
fi
COMPSHAD_VERSION=nxcompshad_version
AC_SUBST([COMPSHAD_VERSION])
LT_COMPSHAD_VERSION=["$(printf '%s\n' "${COMPSHAD_VERSION}" | awk -F '.' '/^[0-9]+\.[0-9]+\.[0-9]+.*$/ { print $1 ":" $2 ":" $3; }')"]
AC_SUBST([LT_COMPSHAD_VERSION])
# Silence warning: ar: 'u' modifier ignored since 'D' is the default
AC_SUBST(AR_FLAGS, [cr])
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_DEFAULT_OPTIONS
NX_TARGET_USE_ELF
AC_ARG_ENABLE([cxx11],
[AS_HELP_STRING([--enable-cxx11],
[enable optional features requiring C++11 support (disabled by default)])],
[AS_IF([test x$enableval = xyes],
[AX_CXX_COMPILE_STDCXX_11([], [mandatory])])])
AC_CONFIG_FILES([
Makefile
src/Makefile
nxcompshad.pc
])
AC_OUTPUT

111
nxcompshad/include/Shadow.h Normal file
View File

@@ -0,0 +1,111 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#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 void NXShadowResetOptions();
extern int NXShadowCreate(void *, char *, char *, void **);
extern void NXShadowDestroy(void);
/*
* Use an already opened Display connection.
* We use <void *> instead of <Display *> 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 */

View File

@@ -0,0 +1 @@
../../m4/ax_cxx_compile_stdcxx.m4

View File

@@ -0,0 +1 @@
../../m4/ax_cxx_compile_stdcxx_11.m4

1
nxcompshad/m4/nx-macros.m4 Symbolic link
View File

@@ -0,0 +1 @@
../../m4/nx-macros.m4

View File

@@ -0,0 +1,13 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: nxcompshad
Description: Shadow Session Support for NX Compression Library
Version: @COMPSHAD_VERSION@
Requires: nxcomp
Requires.private: x11
Cflags: -I${includedir}
Libs: -L${libdir} -lXcompshad

626
nxcompshad/src/Core.cpp Normal file
View File

@@ -0,0 +1,626 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <string.h>
#include <sys/time.h>
#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 (mirror_ == 1)
{
int result = mirrorChanges_;
mirrorChanges_ = 0;
return result;
}
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", "Analyzing 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,
static_cast<short>(curLine),
static_cast<unsigned short>(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, curWorkLine, left, right;
for (curWorkLine = 0; curWorkLine < (int) height_; curWorkLine++)
{
if (lineStatus_[curWorkLine] == LINE_HAS_CHANGED)
{
break;
}
}
start = curWorkLine;
last = curWorkLine;
left = lefts_[curWorkLine];
right = rights_[curWorkLine];
curWorkLine++;
while (1)
{
for (; curWorkLine < (int) height_; curWorkLine++)
{
if (lineStatus_[curWorkLine] == LINE_HAS_CHANGED)
{
break;
}
}
if (curWorkLine == (int) height_)
{
break;
}
if ((curWorkLine - last > minSliceHeight_) ||
(last - start > maxSliceHeight_))
{
XRectangle rect = {static_cast<short>(left),
static_cast<short>(start),
static_cast<unsigned short>(right - left + 1),
static_cast<unsigned short>(last - start + 1)};
XUnionRectWithRegion(&rect, lastUpdatedRegion_, lastUpdatedRegion_);
start = curWorkLine;
left = lefts_[curWorkLine];
right = rights_[curWorkLine];
}
else
{
if (lefts_[curWorkLine] < left)
{
left = lefts_[curWorkLine];
}
if (rights_[curWorkLine] > right)
{
right = rights_[curWorkLine];
}
}
last = curWorkLine;
curWorkLine++;
}
//
// Send last block.
//
if (last >= start)
{
XRectangle rect = {static_cast<short>(left),
static_cast<short>(start),
static_cast<unsigned short>(right - left + 1),
static_cast<unsigned short>(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_];
}
}

208
nxcompshad/src/Core.h Normal file
View File

@@ -0,0 +1,208 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <stdio.h>
#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_;
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 */

179
nxcompshad/src/Input.cpp Normal file
View File

@@ -0,0 +1,179 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <string.h>
#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;
}

99
nxcompshad/src/Input.h Normal file
View File

@@ -0,0 +1,99 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
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 */

128
nxcompshad/src/Logger.cpp Normal file
View File

@@ -0,0 +1,128 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <stdio.h>
#include <ctype.h>
#include <unistd.h>
#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");
}
}

167
nxcompshad/src/Logger.h Normal file
View File

@@ -0,0 +1,167 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <cerrno>
#include <cstdarg>
//
// 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) __attribute__((format(printf, 2, 0)));
void error(const char *name, int error);
void warning(const char *name, const char *format, va_list arguments) __attribute__((format(printf, 3, 0)));
void test(const char *name, const char *format, va_list arguments) __attribute__((format(printf, 3, 0)));
void trace(const char *name);
void debug(const char *name, const char *format, va_list arguments) __attribute__((format(printf, 3, 0)));
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__((format(printf, 2, 3))) __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 */

View File

@@ -0,0 +1,54 @@
NULL =
lib_LTLIBRARIES = libXcompshad.la
libXcompshad_la_SOURCES = \
Core.cpp \
Input.cpp \
Logger.cpp \
Manager.cpp \
Shadow.cpp \
Updater.cpp \
X11.cpp \
$(NULL)
libXcompshad_la_LIBADD = \
-lX11 \
@Xext_LIBS@ \
@Xdamage_LIBS@ \
@Xrandr_LIBS@ \
@Xtst_LIBS@ \
-L$(top_srcdir)/../nx-X11/lib/src/.libs -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 \
-R '$(libdir)/nx/X11' \
$(NULL)
if TARGET_ELF
libXcompshad_la_LDFLAGS += \
-Wl,--enable-new-dtags \
$(NULL)
endif TARGET_ELF
libXcompshadincludedir = $(includedir)/nx
libXcompshadinclude_HEADERS = \
$(top_srcdir)/include/Shadow.h \
$(NULL)

264
nxcompshad/src/Manager.cpp Normal file
View File

@@ -0,0 +1,264 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#include <nx-X11/Xutil.h>
#include <nx-X11/keysym.h>
#include <string.h>
#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<UpdaterHandle>(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<UpdaterHandle>(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", "Caught 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();
}
}

123
nxcompshad/src/Manager.h Normal file
View File

@@ -0,0 +1,123 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#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 */

50
nxcompshad/src/Misc.h Normal file
View File

@@ -0,0 +1,50 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <iostream>
#include <cerrno>
#include <cstring>
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 */

31
nxcompshad/src/Poller.h Normal file
View File

@@ -0,0 +1,31 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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
#include "X11.h"
#endif /* Poller_H */

43
nxcompshad/src/Regions.h Normal file
View File

@@ -0,0 +1,43 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#include <nx-X11/Xutil.h>
typedef struct {
short x1, x2, y1, y2;
} Box, BOX, BoxRec, *BoxPtr;
struct _XRegion {
long size;
long numRects;
BOX *rects;
BOX extents;
};
#endif /* Region_H */

458
nxcompshad/src/Shadow.cpp Normal file
View File

@@ -0,0 +1,458 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <signal.h>
#include <string.h>
#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;
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<Display*>(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<Display*>(dpy);
Display **shadowDisplay = reinterpret_cast<Display**>(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;
}
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);
}
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();
poller -> getEvents();
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);
}
void NXShadowUpdateBuffer(void **buffer)
{
char **fBuffer = reinterpret_cast<char **>(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);
}

395
nxcompshad/src/Updater.cpp Normal file
View File

@@ -0,0 +1,395 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#include <nx-X11/Xutil.h>
#include <nx-X11/keysym.h>
#include <string.h>
#define PANIC
#define WARNING
#undef TEST
#undef DEBUG
//
#include <stdio.h>
//
#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.
//

103
nxcompshad/src/Updater.h Normal file
View File

@@ -0,0 +1,103 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#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 */

1594
nxcompshad/src/X11.cpp Normal file

File diff suppressed because it is too large Load Diff

135
nxcompshad/src/X11.h Normal file
View File

@@ -0,0 +1,135 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* 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 <nx-X11/Xlib.h>
#include <X11/extensions/XShm.h>
#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_;
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 */

View File

@@ -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 <nx-X11/Xfuncproto.h>
_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

View File

@@ -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
* <X11/extensions/Xdamaga.h>
*
* This copy of code has been introduced to allow a clear namespace
* separation between <X11/...> and <nx-X11/...> header files.
*
* This version of the 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 <X11/extensions/Xdamage.h> instead for inclusion in
* nxcompshad, it will attempt pulling in the <X11/extensions/Xfixes.h>
* header which in turn will include <X11/Xlib.h>. However, the headers of
* the same name from <nx-X11/...> should be used instead.
*
* FIXME: Once the nxagent Xserver starts using libX11 from X.Org, this
* hack can be removed.
*
* 2015/06/26, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
*/
#ifndef _XDAMAGE_H_
#define _XDAMAGE_H_
#include <X11/extensions/damagewire.h>
#include <nx-X11/Xfuncproto.h>
/* from <X11/extensions/Xfixes.h> */
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_ */

View File

@@ -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
* <X11/extensions/Xrandr.h>
*
* This copy of code has been introduced to allow a clear namespace
* separation between <X11/...> and <nx-X11/...> header files.
*
* This version of the Xrandr library header file only contains symbols
* required by nxcompshad and strictly avoids indirectly including
* from an X11 library that is also shipped in nx-X11/lib/.
*
* When using <X11/extensions/Xrandr.h> instead for inclusion in
* nxcompshad, it will attempt pulling in the <X11/extensions/Xrender.h>
* header which in turn will include <X11/Xlib.h>. However, the headers of
* the same name from <nx-X11/...> should be used instead.
*
* FIXME: Once the nxagent Xserver starts using libXrender from X.Org, this
* hack can be removed.
*
* 2015/06/26, Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
*/
#ifndef _XRANDR_H_
#define _XRANDR_H_
/* from <X11/extensions/randr.h> */
#define RRScreenChangeNotify 0
#define RRScreenChangeNotifyMask (1L << 0)
#include <X11/Xfuncproto.h>
_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_ */