Initial commit
This commit is contained in:
7
unix/CMakeLists.txt
Normal file
7
unix/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
add_subdirectory(tx)
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(vncconfig)
|
||||
add_subdirectory(vncpasswd)
|
||||
|
||||
install(PROGRAMS vncserver DESTINATION ${BIN_DIR})
|
||||
install(FILES vncserver.man DESTINATION ${MAN_DIR}/man1 RENAME vncserver.1)
|
||||
14
unix/common/CMakeLists.txt
Normal file
14
unix/common/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/unix/common)
|
||||
|
||||
add_library(unixcommon STATIC
|
||||
randr.cxx)
|
||||
|
||||
if(UNIX)
|
||||
libtool_create_control_file(unixcommon)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
set_target_properties(unixcommon
|
||||
PROPERTIES COMPILE_FLAGS -fPIC)
|
||||
endif()
|
||||
68
unix/common/RandrGlue.h
Normal file
68
unix/common/RandrGlue.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
This header defines an interface for X RandR operations. It is
|
||||
implemented by a corresponding RandrGlue.c, either with internal
|
||||
calls (for Xvnc/vncmodule.so) or Xlib calls (x0vncserver).
|
||||
*/
|
||||
|
||||
#ifndef RANDR_GLUE_H
|
||||
#define RANDR_GLUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int vncGetScreenWidth(void);
|
||||
int vncGetScreenHeight(void);
|
||||
|
||||
int vncRandRIsValidScreenSize(int width, int height);
|
||||
int vncRandRResizeScreen(int width, int height);
|
||||
void vncRandRUpdateSetTime(void);
|
||||
|
||||
int vncRandRHasOutputClones(void);
|
||||
|
||||
int vncRandRGetOutputCount(void);
|
||||
int vncRandRGetAvailableOutputs(void);
|
||||
|
||||
char *vncRandRGetOutputName(int outputIdx);
|
||||
|
||||
int vncRandRIsOutputEnabled(int outputIdx);
|
||||
int vncRandRIsOutputUsable(int outputIdx);
|
||||
int vncRandRIsOutputConnected(int outputIdx);
|
||||
|
||||
int vncRandRCheckOutputMode(int outputIdx, int width, int height);
|
||||
|
||||
int vncRandRDisableOutput(int outputIdx);
|
||||
int vncRandRReconfigureOutput(int outputIdx, int x, int y,
|
||||
int width, int height);
|
||||
|
||||
unsigned int vncRandRGetOutputId(int outputIdx);
|
||||
int vncRandRGetOutputDimensions(int outputIdx,
|
||||
int *x, int *y, int *width, int *height);
|
||||
|
||||
int vncRandRCanCreateOutputs(int extraOutputs);
|
||||
int vncRandRCreateOutputs(int extraOutputs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
447
unix/common/randr.cxx
Normal file
447
unix/common/randr.cxx
Normal file
@@ -0,0 +1,447 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2009-2017 Pierre Ossman for Cendio AB
|
||||
* Copyright 2018 Peter Astrand <astrand@cendio.se> for Cendio AB
|
||||
* Copyright 2014 Brian P. Hinz
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <unixcommon.h>
|
||||
#include <rfb/screenTypes.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <RandrGlue.h>
|
||||
static rfb::LogWriter vlog("RandR");
|
||||
|
||||
static int ResizeScreen(bool dryrun, int fb_width, int fb_height,
|
||||
std::set<unsigned int>* disabledOutputs)
|
||||
{
|
||||
vlog.debug("Resizing screen framebuffer to %dx%d", fb_width, fb_height);
|
||||
|
||||
/*
|
||||
* Disable outputs which are larger than the target size
|
||||
*/
|
||||
for (int i = 0;i < vncRandRGetOutputCount();i++) {
|
||||
int x, y, width, height;
|
||||
if (vncRandRGetOutputDimensions(i, &x, &y, &width, &height) == 0) {
|
||||
if (x + width > fb_width || y + height > fb_height) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.debug("Temporarily disabling output '%s'", name);
|
||||
free(name);
|
||||
if (!dryrun) {
|
||||
/* Currently ignoring errors */
|
||||
/* FIXME: Save output rotation and restore when configuring output */
|
||||
vncRandRDisableOutput(i);
|
||||
disabledOutputs->insert(vncRandRGetOutputId(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!vncRandRIsValidScreenSize(fb_width, fb_height))
|
||||
return 0;
|
||||
|
||||
if (dryrun)
|
||||
return 1;
|
||||
|
||||
return vncRandRResizeScreen(fb_width, fb_height);
|
||||
}
|
||||
|
||||
|
||||
/* Return output index of preferred output, -1 on failure */
|
||||
int getPreferredScreenOutput(OutputIdMap *outputIdMap,
|
||||
const std::set<unsigned int>& disabledOutputs)
|
||||
{
|
||||
int firstDisabled = -1;
|
||||
int firstEnabled = -1;
|
||||
int firstConnected = -1;
|
||||
int firstUsable = -1;
|
||||
|
||||
for (int i = 0;i < vncRandRGetOutputCount();i++) {
|
||||
unsigned int output = vncRandRGetOutputId(i);
|
||||
|
||||
/* In use? */
|
||||
if (outputIdMap->count(output) == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Can it be used? */
|
||||
if (!vncRandRIsOutputUsable(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Temporarily disabled? */
|
||||
if (disabledOutputs.count(output)) {
|
||||
if (firstDisabled == -1) firstDisabled = i;
|
||||
}
|
||||
|
||||
/* Enabled? */
|
||||
if (vncRandRIsOutputEnabled(i)) {
|
||||
if (firstEnabled == -1) firstEnabled = i;
|
||||
}
|
||||
|
||||
/* Connected? */
|
||||
if (vncRandRIsOutputConnected(i)) {
|
||||
if (firstConnected == -1) firstConnected = i;
|
||||
}
|
||||
|
||||
if (firstUsable == -1) firstUsable = i;
|
||||
}
|
||||
|
||||
if (firstEnabled != -1) {
|
||||
return firstEnabled;
|
||||
} else if (firstDisabled != -1) {
|
||||
return firstDisabled;
|
||||
} else if (firstConnected != -1) {
|
||||
return firstConnected;
|
||||
} else {
|
||||
return firstUsable; /* Possibly -1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rfb::ScreenSet computeScreenLayout(OutputIdMap *outputIdMap)
|
||||
{
|
||||
rfb::ScreenSet layout;
|
||||
OutputIdMap newIdMap;
|
||||
|
||||
for (int i = 0;i < vncRandRGetOutputCount();i++) {
|
||||
unsigned int outputId;
|
||||
int x, y, width, height;
|
||||
|
||||
/* Disabled? */
|
||||
if (!vncRandRIsOutputEnabled(i))
|
||||
continue;
|
||||
|
||||
outputId = vncRandRGetOutputId(i);
|
||||
|
||||
/* Known output? */
|
||||
if (outputIdMap->count(outputId) == 1)
|
||||
newIdMap[outputId] = (*outputIdMap)[outputId];
|
||||
else {
|
||||
rdr::U32 id;
|
||||
OutputIdMap::const_iterator iter;
|
||||
|
||||
while (true) {
|
||||
id = rand();
|
||||
for (iter = outputIdMap->begin();iter != outputIdMap->end();++iter) {
|
||||
if (iter->second == id)
|
||||
break;
|
||||
}
|
||||
if (iter == outputIdMap->end())
|
||||
break;
|
||||
}
|
||||
|
||||
newIdMap[outputId] = id;
|
||||
}
|
||||
|
||||
if (vncRandRGetOutputDimensions(i, &x, &y, &width, &height) == 0) {
|
||||
layout.add_screen(rfb::Screen(newIdMap[outputId], x, y, width, height, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/* Only keep the entries that are currently active */
|
||||
*outputIdMap = newIdMap;
|
||||
|
||||
/*
|
||||
* Make sure we have something to display. Hopefully it's just temporary
|
||||
* that we have no active outputs...
|
||||
*/
|
||||
if (layout.num_screens() == 0)
|
||||
layout.add_screen(rfb::Screen(0, 0, 0, vncGetScreenWidth(),
|
||||
vncGetScreenHeight(), 0));
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
static unsigned int _setScreenLayout(bool dryrun,
|
||||
int fb_width, int fb_height, const rfb::ScreenSet& layout,
|
||||
OutputIdMap *outputIdMap)
|
||||
{
|
||||
int ret;
|
||||
int availableOutputs;
|
||||
std::set<unsigned int> disabledOutputs;
|
||||
/* Printing errors in the dryrun pass might be confusing */
|
||||
const bool logErrors = !dryrun || vlog.getLevel() >= vlog.LEVEL_DEBUG;
|
||||
|
||||
// RandR support?
|
||||
if (vncRandRGetOutputCount() == 0)
|
||||
return rfb::resultProhibited;
|
||||
|
||||
/*
|
||||
* First check that we don't have any active clone modes. That's just
|
||||
* too messy to deal with.
|
||||
*/
|
||||
if (vncRandRHasOutputClones()) {
|
||||
if (logErrors) {
|
||||
vlog.error("Clone mode active. Refusing to touch screen layout.");
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
/* Next count how many useful outputs we have... */
|
||||
availableOutputs = vncRandRGetAvailableOutputs();
|
||||
|
||||
/* Try to create more outputs if needed... (only works on Xvnc) */
|
||||
if (layout.num_screens() > availableOutputs) {
|
||||
vlog.debug("Insufficient screens. Need to create %d more.",
|
||||
layout.num_screens() - availableOutputs);
|
||||
|
||||
if (!vncRandRCanCreateOutputs(layout.num_screens() - availableOutputs)) {
|
||||
if (logErrors)
|
||||
vlog.error("Unable to create more screens, as needed by the new client layout.");
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
if (!dryrun) {
|
||||
ret = vncRandRCreateOutputs(layout.num_screens() - availableOutputs);
|
||||
if (!ret) {
|
||||
if (logErrors)
|
||||
vlog.error("Unable to create more screens, as needed by the new client layout.");
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* First we might need to resize the screen */
|
||||
if ((fb_width != vncGetScreenWidth()) ||
|
||||
(fb_height != vncGetScreenHeight())) {
|
||||
ret = ResizeScreen(dryrun, fb_width, fb_height, &disabledOutputs);
|
||||
if (!ret) {
|
||||
if (logErrors) {
|
||||
vlog.error("Failed to resize screen to %dx%d", fb_width, fb_height);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next, reconfigure all known outputs */
|
||||
for (int i = 0;i < vncRandRGetOutputCount();i++) {
|
||||
unsigned int output;
|
||||
|
||||
rfb::ScreenSet::const_iterator iter;
|
||||
|
||||
output = vncRandRGetOutputId(i);
|
||||
|
||||
/* Known? */
|
||||
if (outputIdMap->count(output) == 0)
|
||||
continue;
|
||||
|
||||
/* Find the corresponding screen... */
|
||||
for (iter = layout.begin();iter != layout.end();++iter) {
|
||||
if (iter->id == (*outputIdMap)[output])
|
||||
break;
|
||||
}
|
||||
|
||||
/* Missing? */
|
||||
if (iter == layout.end()) {
|
||||
ret = vncRandRDisableOutput(i);
|
||||
if (!ret) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Failed to disable unused output '%s'",
|
||||
name);
|
||||
free(name);
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
outputIdMap->erase(output);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Probably not needed, but let's be safe */
|
||||
if (!vncRandRIsOutputUsable(i)) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Required output '%s' cannot be used", name);
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
/* Possible mode? */
|
||||
if (!vncRandRCheckOutputMode(i, iter->dimensions.width(),
|
||||
iter->dimensions.height())) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Output '%s' does not support required mode %dx%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height());
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.debug("Reconfiguring output '%s' to %dx%d+%d+%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height(),
|
||||
iter->dimensions.tl.x, iter->dimensions.tl.y);
|
||||
free(name);
|
||||
|
||||
if (dryrun)
|
||||
continue;
|
||||
|
||||
/* Reconfigure new mode and position */
|
||||
ret = vncRandRReconfigureOutput(i,
|
||||
iter->dimensions.tl.x,
|
||||
iter->dimensions.tl.y,
|
||||
iter->dimensions.width(),
|
||||
iter->dimensions.height());
|
||||
if (!ret) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Failed to reconfigure output '%s' to %dx%d+%d+%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height(),
|
||||
iter->dimensions.tl.x, iter->dimensions.tl.y);
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate new outputs for new screens */
|
||||
rfb::ScreenSet::const_iterator iter;
|
||||
for (iter = layout.begin();iter != layout.end();++iter) {
|
||||
OutputIdMap::const_iterator oi;
|
||||
unsigned int output;
|
||||
int i;
|
||||
|
||||
/* Does this screen have an output already? */
|
||||
for (oi = outputIdMap->begin();oi != outputIdMap->end();++oi) {
|
||||
if (oi->second == iter->id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (oi != outputIdMap->end())
|
||||
continue;
|
||||
|
||||
/* Find an unused output */
|
||||
i = getPreferredScreenOutput(outputIdMap, disabledOutputs);
|
||||
|
||||
/* Shouldn't happen */
|
||||
if (i == -1)
|
||||
return rfb::resultInvalid;
|
||||
output = vncRandRGetOutputId(i);
|
||||
|
||||
/*
|
||||
* Make sure we already have an entry for this, or
|
||||
* computeScreenLayout() will think it is a brand new output and
|
||||
* assign it a random id.
|
||||
*/
|
||||
(*outputIdMap)[output] = iter->id;
|
||||
|
||||
/* Probably not needed, but let's be safe */
|
||||
if (!vncRandRIsOutputUsable(i)) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Required new output '%s' cannot be used", name);
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
/* Possible mode? */
|
||||
if (!vncRandRCheckOutputMode(i, iter->dimensions.width(),
|
||||
iter->dimensions.height())) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("New output '%s' does not support required mode %dx%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height());
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.debug("Reconfiguring new output '%s' to %dx%d+%d+%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height(),
|
||||
iter->dimensions.tl.x, iter->dimensions.tl.y);
|
||||
free(name);
|
||||
|
||||
if (dryrun)
|
||||
continue;
|
||||
|
||||
/* Reconfigure new mode and position */
|
||||
ret = vncRandRReconfigureOutput(i,
|
||||
iter->dimensions.tl.x,
|
||||
iter->dimensions.tl.y,
|
||||
iter->dimensions.width(),
|
||||
iter->dimensions.height());
|
||||
if (!ret) {
|
||||
if (logErrors) {
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
vlog.error("Failed to reconfigure new output '%s' to %dx%d+%d+%d", name,
|
||||
iter->dimensions.width(), iter->dimensions.height(),
|
||||
iter->dimensions.tl.x, iter->dimensions.tl.y);
|
||||
free(name);
|
||||
}
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn off unused outputs */
|
||||
for (int i = 0;i < vncRandRGetOutputCount();i++) {
|
||||
unsigned int output = vncRandRGetOutputId(i);
|
||||
|
||||
/* Known? */
|
||||
if (outputIdMap->count(output) == 1)
|
||||
continue;
|
||||
|
||||
/* Enabled? */
|
||||
if (!vncRandRIsOutputEnabled(i))
|
||||
continue;
|
||||
|
||||
/* Disable and move on... */
|
||||
ret = vncRandRDisableOutput(i);
|
||||
char *name = vncRandRGetOutputName(i);
|
||||
if (ret) {
|
||||
vlog.debug("Disabled unused output '%s'", name);
|
||||
} else {
|
||||
if (logErrors) {
|
||||
vlog.error("Failed to disable unused output '%s'", name);
|
||||
}
|
||||
free(name);
|
||||
return rfb::resultInvalid;
|
||||
}
|
||||
free(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update timestamp for when screen layout was last changed.
|
||||
* This is normally done in the X11 request handlers, which is
|
||||
* why we have to deal with it manually here.
|
||||
*/
|
||||
vncRandRUpdateSetTime();
|
||||
|
||||
return rfb::resultSuccess;
|
||||
}
|
||||
|
||||
|
||||
unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,
|
||||
OutputIdMap *outputIdMap)
|
||||
{
|
||||
return _setScreenLayout(false, fb_width, fb_height, layout, outputIdMap);
|
||||
}
|
||||
|
||||
|
||||
unsigned int tryScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,
|
||||
OutputIdMap *outputIdMap)
|
||||
{
|
||||
OutputIdMap dryrunIdMap = *outputIdMap;
|
||||
return _setScreenLayout(true, fb_width, fb_height, layout, &dryrunIdMap);
|
||||
}
|
||||
48
unix/common/unixcommon.h
Normal file
48
unix/common/unixcommon.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2009-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef UNIXCOMMON_H
|
||||
#define UNIXCOMMON_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <rfb/ScreenSet.h>
|
||||
|
||||
typedef std::map<unsigned int, rdr::U32> OutputIdMap;
|
||||
|
||||
rfb::ScreenSet computeScreenLayout(OutputIdMap *outputIdMap);
|
||||
|
||||
unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,
|
||||
OutputIdMap *outputIdMap);
|
||||
|
||||
unsigned int tryScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout,
|
||||
OutputIdMap *outputIdMap);
|
||||
|
||||
/*
|
||||
* FIXME: This is only exposed because we still have logic in XDesktop
|
||||
* that we haven't integrated in setScreenLayout()
|
||||
*/
|
||||
int getPreferredScreenOutput(OutputIdMap *outputIdMap,
|
||||
const std::set<unsigned int>& disabledOutputs);
|
||||
|
||||
#endif /* UNIXCOMMON_H */
|
||||
9
unix/tx/CMakeLists.txt
Normal file
9
unix/tx/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/common/rfb)
|
||||
|
||||
add_library(tx STATIC
|
||||
TXWindow.cxx)
|
||||
|
||||
target_link_libraries(tx ${X11_LIBRARIES})
|
||||
124
unix/tx/TXButton.h
Normal file
124
unix/tx/TXButton.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXButton.h
|
||||
//
|
||||
// A TXButton is a clickable button with some text in it. The button must be
|
||||
// big enough to contain the text - if not then it will be resized
|
||||
// appropriately.
|
||||
//
|
||||
|
||||
#ifndef __TXBUTTON_H__
|
||||
#define __TXBUTTON_H__
|
||||
|
||||
#include "TXWindow.h"
|
||||
#include <rfb/util.h>
|
||||
|
||||
// TXButtonCallback's buttonActivate() method is called when a button is
|
||||
// activated.
|
||||
class TXButton;
|
||||
class TXButtonCallback {
|
||||
public:
|
||||
virtual void buttonActivate(TXButton* button)=0;
|
||||
};
|
||||
|
||||
|
||||
class TXButton : public TXWindow, public TXEventHandler {
|
||||
public:
|
||||
|
||||
TXButton(Display* dpy_, const char* text_, TXButtonCallback* cb_=0,
|
||||
TXWindow* parent_=0, int w=1, int h=1)
|
||||
: TXWindow(dpy_, w, h, parent_), cb(cb_), down(false),
|
||||
disabled_(false)
|
||||
{
|
||||
setEventHandler(this);
|
||||
setText(text_);
|
||||
gc = XCreateGC(dpy, win(), 0, 0);
|
||||
XSetFont(dpy, gc, defaultFont);
|
||||
addEventMask(ExposureMask | ButtonPressMask | ButtonReleaseMask);
|
||||
}
|
||||
|
||||
virtual ~TXButton() {
|
||||
XFreeGC(dpy, gc);
|
||||
}
|
||||
|
||||
// setText() changes the text in the button.
|
||||
void setText(const char* text_) {
|
||||
text.buf = rfb::strDup(text_);
|
||||
int textWidth = XTextWidth(defaultFS, text.buf, strlen(text.buf));
|
||||
int textHeight = (defaultFS->ascent + defaultFS->descent);
|
||||
int newWidth = __rfbmax(width(), textWidth + xPad*2 + bevel*2);
|
||||
int newHeight = __rfbmax(height(), textHeight + yPad*2 + bevel*2);
|
||||
if (width() < newWidth || height() < newHeight) {
|
||||
resize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// disabled() sets or queries the disabled state of the checkbox. A disabled
|
||||
// checkbox cannot be changed via the user interface.
|
||||
void disabled(bool b) { disabled_ = b; paint(); }
|
||||
bool disabled() { return disabled_; }
|
||||
|
||||
private:
|
||||
|
||||
void paint() {
|
||||
int tw = XTextWidth(defaultFS, text.buf, strlen(text.buf));
|
||||
int startx = (width() - tw) / 2;
|
||||
int starty = (height() + defaultFS->ascent - defaultFS->descent) / 2;
|
||||
if (down || disabled_) {
|
||||
drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, darkBg,lightBg);
|
||||
startx++; starty++;
|
||||
} else {
|
||||
drawBevel(gc, 0, 0, width(), height(), bevel, defaultBg, lightBg,darkBg);
|
||||
}
|
||||
|
||||
XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg);
|
||||
XDrawString(dpy, win(), gc, startx, starty, text.buf, strlen(text.buf));
|
||||
}
|
||||
|
||||
virtual void handleEvent(TXWindow* w, XEvent* ev) {
|
||||
switch (ev->type) {
|
||||
case Expose:
|
||||
paint();
|
||||
break;
|
||||
case ButtonPress:
|
||||
if (!disabled_) {
|
||||
down = true;
|
||||
paint();
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (!down) break;
|
||||
down = false;
|
||||
paint();
|
||||
if (ev->xbutton.x >= 0 && ev->xbutton.x < width() &&
|
||||
ev->xbutton.y >= 0 && ev->xbutton.y < height()) {
|
||||
if (cb) cb->buttonActivate(this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GC gc;
|
||||
rfb::CharArray text;
|
||||
TXButtonCallback* cb;
|
||||
bool down;
|
||||
bool disabled_;
|
||||
};
|
||||
|
||||
#endif
|
||||
142
unix/tx/TXCheckbox.h
Normal file
142
unix/tx/TXCheckbox.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXCheckbox.h
|
||||
//
|
||||
// A TXCheckbox has a box which may be "checked" with some text next to it.
|
||||
// The checkbox window must be big enough to contain the text - if not then it
|
||||
// will be resized appropriately.
|
||||
//
|
||||
// There are two styles of checkbox: the normal style which uses a tick in a
|
||||
// square box, and the radio style which uses a dot inside a circle. The
|
||||
// default behaviour when clicking on the checkbox is to toggle it on or off,
|
||||
// but this behaviour can be changed by the callback object. In particular to
|
||||
// get radiobutton behaviour, the callback must ensure that only one of a set
|
||||
// of radiobuttons is selected.
|
||||
//
|
||||
|
||||
#ifndef __TXCHECKBOX_H__
|
||||
#define __TXCHECKBOX_H__
|
||||
|
||||
#include "TXWindow.h"
|
||||
#include <rfb/util.h>
|
||||
|
||||
// TXCheckboxCallback's checkboxSelect() method is called when the state of a
|
||||
// checkbox changes.
|
||||
class TXCheckbox;
|
||||
class TXCheckboxCallback {
|
||||
public:
|
||||
virtual void checkboxSelect(TXCheckbox* checkbox)=0;
|
||||
};
|
||||
|
||||
|
||||
class TXCheckbox : public TXWindow, public TXEventHandler {
|
||||
public:
|
||||
TXCheckbox(Display* dpy_, const char* text_, TXCheckboxCallback* cb_,
|
||||
bool radio_=false, TXWindow* parent_=0, int w=1, int h=1)
|
||||
: TXWindow(dpy_, w, h, parent_), cb(cb_), text(0),
|
||||
boxSize(radio_ ? 12 : 13), boxPad(4),
|
||||
checked_(false), disabled_(false), radio(radio_)
|
||||
{
|
||||
setEventHandler(this);
|
||||
setText(text_);
|
||||
gc = XCreateGC(dpy, win(), 0, 0);
|
||||
XSetFont(dpy, gc, defaultFont);
|
||||
addEventMask(ExposureMask| ButtonPressMask | ButtonReleaseMask);
|
||||
}
|
||||
|
||||
virtual ~TXCheckbox() {
|
||||
XFreeGC(dpy, gc);
|
||||
if (text) free(text);
|
||||
}
|
||||
|
||||
// setText() changes the text in the checkbox.
|
||||
void setText(const char* text_) {
|
||||
if (text) free(text);
|
||||
text = strdup((char*)text_);
|
||||
int textWidth = XTextWidth(defaultFS, text, strlen(text));
|
||||
int textHeight = (defaultFS->ascent + defaultFS->descent);
|
||||
int newWidth = __rfbmax(width(), textWidth + xPad*2 + boxPad*2 + boxSize);
|
||||
int newHeight = __rfbmax(height(), textHeight + yPad*2);
|
||||
if (width() < newWidth || height() < newHeight) {
|
||||
resize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// checked() sets or queries the state of the checkbox
|
||||
void checked(bool b) { checked_ = b; paint(); }
|
||||
bool checked() { return checked_; }
|
||||
|
||||
// disabled() sets or queries the disabled state of the checkbox. A disabled
|
||||
// checkbox cannot be changed via the user interface.
|
||||
void disabled(bool b) { disabled_ = b; paint(); }
|
||||
bool disabled() { return disabled_; }
|
||||
|
||||
private:
|
||||
void paint() {
|
||||
if (disabled_)
|
||||
drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize,
|
||||
bevel, disabledBg, darkBg, lightBg, radio);
|
||||
else
|
||||
drawBevel(gc, xPad + boxPad, (height() - boxSize) / 2, boxSize, boxSize,
|
||||
bevel, enabledBg, darkBg, lightBg, radio);
|
||||
XSetBackground(dpy, gc, disabled_ ? disabledBg : enabledBg);
|
||||
XSetForeground(dpy, gc, disabled_ ? disabledFg : defaultFg);
|
||||
if (checked_) {
|
||||
Pixmap icon = radio ? dot : tick;
|
||||
int iconSize = radio ? dotSize : tickSize;
|
||||
XCopyPlane(dpy, icon, win(), gc, 0, 0, iconSize, iconSize,
|
||||
xPad + boxPad + (boxSize - iconSize) / 2,
|
||||
(height() - iconSize) / 2, 1);
|
||||
}
|
||||
XDrawString(dpy, win(), gc, xPad + boxSize + boxPad*2,
|
||||
(height() + defaultFS->ascent - defaultFS->descent) / 2,
|
||||
text, strlen(text));
|
||||
}
|
||||
|
||||
virtual void handleEvent(TXWindow* w, XEvent* ev) {
|
||||
switch (ev->type) {
|
||||
case Expose:
|
||||
paint();
|
||||
break;
|
||||
case ButtonPress:
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (ev->xbutton.x >= 0 && ev->xbutton.x < width() &&
|
||||
ev->xbutton.y >= 0 && ev->xbutton.y < height()) {
|
||||
if (!disabled_) {
|
||||
checked_ = !checked_;
|
||||
if (cb) cb->checkboxSelect(this);
|
||||
paint();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TXCheckboxCallback* cb;
|
||||
GC gc;
|
||||
char* text;
|
||||
int boxSize;
|
||||
int boxPad;
|
||||
bool checked_;
|
||||
bool disabled_;
|
||||
bool radio;
|
||||
};
|
||||
|
||||
#endif
|
||||
96
unix/tx/TXDialog.h
Normal file
96
unix/tx/TXDialog.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXDialog.h
|
||||
//
|
||||
// A TXDialog is a pop-up dialog window. The dialog can be made visible by
|
||||
// calling its show() method. Dialogs can be modal or non-modal. For a modal
|
||||
// dialog box, the show() method only returns when the dialog box has been
|
||||
// dismissed. For a non-modal dialog box, the show() method returns
|
||||
// immediately.
|
||||
//
|
||||
|
||||
#ifndef __TXDIALOG_H__
|
||||
#define __TXDIALOG_H__
|
||||
|
||||
#include "TXWindow.h"
|
||||
#include <errno.h>
|
||||
|
||||
class TXDialog : public TXWindow, public TXDeleteWindowCallback {
|
||||
public:
|
||||
TXDialog(Display* dpy, int width, int height, const char* name,
|
||||
bool modal_=false)
|
||||
: TXWindow(dpy, width, height), done(false), ok(false), modal(modal_)
|
||||
{
|
||||
toplevel(name, this);
|
||||
resize(width, height);
|
||||
}
|
||||
|
||||
virtual ~TXDialog() {}
|
||||
|
||||
// show() makes the dialog visible. For a modal dialog box, this processes X
|
||||
// events until the done flag has been set, after which it returns the value
|
||||
// of the ok flag. For a non-modal dialog box it always returns true
|
||||
// immediately.
|
||||
bool show() {
|
||||
ok = false;
|
||||
done = false;
|
||||
initDialog();
|
||||
raise();
|
||||
map();
|
||||
if (modal) {
|
||||
while (true) {
|
||||
TXWindow::handleXEvents(dpy);
|
||||
if (done) {
|
||||
return ok;
|
||||
}
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ConnectionNumber(dpy), &rfds);
|
||||
int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
|
||||
if (n < 0) throw rdr::SystemException("select",errno);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// initDialog() can be overridden in a derived class. Typically it is used
|
||||
// to make sure that checkboxes have the right state, etc.
|
||||
virtual void initDialog() {}
|
||||
|
||||
// resize() is overridden here to re-center the dialog
|
||||
void resize(int w, int h) {
|
||||
TXWindow::resize(w,h);
|
||||
int dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
|
||||
int dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
|
||||
setUSPosition((dpyWidth - width() - 10) / 2, (dpyHeight - height() - 30) / 2);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void deleteWindow(TXWindow* w) {
|
||||
ok = false;
|
||||
done = true;
|
||||
unmap();
|
||||
}
|
||||
|
||||
bool done;
|
||||
bool ok;
|
||||
bool modal;
|
||||
};
|
||||
|
||||
#endif
|
||||
126
unix/tx/TXLabel.h
Normal file
126
unix/tx/TXLabel.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXLabel.h
|
||||
//
|
||||
// An TXLabel allows you to put up multiline text in a window with various
|
||||
// alignments. The label must be big enough to contain the text - if not then
|
||||
// it will be resized appropriately.
|
||||
//
|
||||
|
||||
#ifndef __TXLABEL_H__
|
||||
#define __TXLABEL_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "TXWindow.h"
|
||||
#include <rfb/util.h>
|
||||
|
||||
class TXLabel : public TXWindow, public TXEventHandler {
|
||||
public:
|
||||
enum HAlign { left, centre, right };
|
||||
enum VAlign { top, middle, bottom };
|
||||
|
||||
TXLabel(Display* dpy_, const char* text_, TXWindow* parent_=0,
|
||||
int w=1, int h=1, HAlign ha=centre, VAlign va=middle)
|
||||
: TXWindow(dpy_, w, h, parent_), lineSpacing(2), lines(0),
|
||||
halign(ha), valign(va)
|
||||
{
|
||||
setEventHandler(this);
|
||||
setText(text_);
|
||||
addEventMask(ExposureMask);
|
||||
}
|
||||
|
||||
// setText() changes the text in the label.
|
||||
void setText(const char* text_) {
|
||||
text.buf = rfb::strDup(text_);
|
||||
lines = 0;
|
||||
int lineStart = 0;
|
||||
int textWidth = 0;
|
||||
int i = -1;
|
||||
do {
|
||||
i++;
|
||||
if (text.buf[i] == '\n' || text.buf[i] == 0) {
|
||||
int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart);
|
||||
if (tw > textWidth) textWidth = tw;
|
||||
lineStart = i+1;
|
||||
lines++;
|
||||
}
|
||||
} while (text.buf[i] != 0);
|
||||
int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing)
|
||||
* lines);
|
||||
int newWidth = __rfbmax(width(), textWidth + xPad*2);
|
||||
int newHeight = __rfbmax(height(), textHeight + yPad*2);
|
||||
if (width() < newWidth || height() < newHeight) {
|
||||
resize(newWidth, newHeight);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private:
|
||||
int xOffset(int textWidth) {
|
||||
switch (halign) {
|
||||
case left: return xPad;
|
||||
case right: return width() - xPad - textWidth;
|
||||
default: return (width() - textWidth) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
int yOffset(int lineNum) {
|
||||
int textHeight = ((defaultFS->ascent + defaultFS->descent + lineSpacing)
|
||||
* lines);
|
||||
int lineOffset = ((defaultFS->ascent + defaultFS->descent + lineSpacing)
|
||||
* lineNum + defaultFS->ascent);
|
||||
switch (valign) {
|
||||
case top: return yPad + lineOffset;
|
||||
case bottom: return height() - yPad - textHeight + lineOffset;
|
||||
default: return (height() - textHeight) / 2 + lineOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void paint() {
|
||||
int lineNum = 0;
|
||||
int lineStart = 0;
|
||||
int i = -1;
|
||||
do {
|
||||
i++;
|
||||
if (text.buf[i] == '\n' || text.buf[i] == 0) {
|
||||
int tw = XTextWidth(defaultFS, &text.buf[lineStart], i-lineStart);
|
||||
XDrawString(dpy, win(), defaultGC, xOffset(tw), yOffset(lineNum),
|
||||
&text.buf[lineStart], i-lineStart);
|
||||
lineStart = i+1;
|
||||
lineNum++;
|
||||
}
|
||||
} while (text.buf[i] != 0);
|
||||
}
|
||||
|
||||
virtual void handleEvent(TXWindow* w, XEvent* ev) {
|
||||
switch (ev->type) {
|
||||
case Expose:
|
||||
paint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int lineSpacing;
|
||||
rfb::CharArray text;
|
||||
int lines;
|
||||
HAlign halign;
|
||||
VAlign valign;
|
||||
};
|
||||
|
||||
#endif
|
||||
513
unix/tx/TXWindow.cxx
Normal file
513
unix/tx/TXWindow.cxx
Normal file
@@ -0,0 +1,513 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXWindow.cxx
|
||||
//
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include "TXWindow.h"
|
||||
#include <list>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <rfb/util.h>
|
||||
|
||||
std::list<TXWindow*> windows;
|
||||
|
||||
Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
|
||||
Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
|
||||
Atom xaCLIPBOARD;
|
||||
unsigned long TXWindow::black, TXWindow::white;
|
||||
unsigned long TXWindow::defaultFg, TXWindow::defaultBg;
|
||||
unsigned long TXWindow::lightBg, TXWindow::darkBg;
|
||||
unsigned long TXWindow::disabledFg, TXWindow::disabledBg;
|
||||
unsigned long TXWindow::enabledBg;
|
||||
unsigned long TXWindow::scrollbarBg;
|
||||
Colormap TXWindow::cmap = 0;
|
||||
GC TXWindow::defaultGC = 0;
|
||||
Font TXWindow::defaultFont = 0;
|
||||
XFontStruct* TXWindow::defaultFS = 0;
|
||||
Time TXWindow::cutBufferTime = 0;
|
||||
Pixmap TXWindow::dot = 0, TXWindow::tick = 0;
|
||||
const int TXWindow::dotSize = 4, TXWindow::tickSize = 8;
|
||||
char* TXWindow::defaultWindowClass;
|
||||
|
||||
TXGlobalEventHandler* TXWindow::globalEventHandler = NULL;
|
||||
|
||||
void TXWindow::init(Display* dpy, const char* defaultWindowClass_)
|
||||
{
|
||||
cmap = DefaultColormap(dpy,DefaultScreen(dpy));
|
||||
wmProtocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
||||
wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
wmTakeFocus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
|
||||
xaTIMESTAMP = XInternAtom(dpy, "TIMESTAMP", False);
|
||||
xaTARGETS = XInternAtom(dpy, "TARGETS", False);
|
||||
xaSELECTION_TIME = XInternAtom(dpy, "SELECTION_TIME", False);
|
||||
xaSELECTION_STRING = XInternAtom(dpy, "SELECTION_STRING", False);
|
||||
xaCLIPBOARD = XInternAtom(dpy, "CLIPBOARD", False);
|
||||
XColor cols[6];
|
||||
cols[0].red = cols[0].green = cols[0].blue = 0x0000;
|
||||
cols[1].red = cols[1].green = cols[1].blue = 0xbbbb;
|
||||
cols[2].red = cols[2].green = cols[2].blue = 0xeeee;
|
||||
cols[3].red = cols[3].green = cols[3].blue = 0x5555;
|
||||
cols[4].red = cols[4].green = cols[4].blue = 0x8888;
|
||||
cols[5].red = cols[5].green = cols[5].blue = 0xffff;
|
||||
getColours(dpy, cols, 6);
|
||||
black = defaultFg = cols[0].pixel;
|
||||
defaultBg = disabledBg = cols[1].pixel;
|
||||
lightBg = cols[2].pixel;
|
||||
darkBg = disabledFg = cols[3].pixel;
|
||||
scrollbarBg = cols[4].pixel;
|
||||
white = enabledBg = cols[5].pixel;
|
||||
defaultGC = XCreateGC(dpy, DefaultRootWindow(dpy), 0, 0);
|
||||
defaultFS
|
||||
= XLoadQueryFont(dpy, "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*");
|
||||
if (!defaultFS) {
|
||||
defaultFS = XLoadQueryFont(dpy, "fixed");
|
||||
if (!defaultFS) {
|
||||
fprintf(stderr,"Failed to load any font\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
defaultFont = defaultFS->fid;
|
||||
XSetForeground(dpy, defaultGC, defaultFg);
|
||||
XSetBackground(dpy, defaultGC, defaultBg);
|
||||
XSetFont(dpy, defaultGC, defaultFont);
|
||||
XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask);
|
||||
|
||||
static unsigned char dotBits[] = { 0x06, 0x0f, 0x0f, 0x06};
|
||||
dot = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), (char*)dotBits,
|
||||
dotSize, dotSize);
|
||||
static unsigned char tickBits[] = { 0x80, 0xc0, 0xe2, 0x76, 0x3e, 0x1c, 0x08, 0x00};
|
||||
tick = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), (char*)tickBits,
|
||||
tickSize, tickSize);
|
||||
defaultWindowClass = rfb::strDup(defaultWindowClass_);
|
||||
}
|
||||
|
||||
void TXWindow::handleXEvents(Display* dpy)
|
||||
{
|
||||
while (XPending(dpy)) {
|
||||
XEvent ev;
|
||||
XNextEvent(dpy, &ev);
|
||||
if (globalEventHandler) {
|
||||
if (globalEventHandler->handleGlobalEvent(&ev))
|
||||
continue;
|
||||
}
|
||||
if (ev.type == MappingNotify) {
|
||||
XRefreshKeyboardMapping(&ev.xmapping);
|
||||
} else if (ev.type == PropertyNotify &&
|
||||
ev.xproperty.window == DefaultRootWindow(dpy) &&
|
||||
ev.xproperty.atom == XA_CUT_BUFFER0) {
|
||||
cutBufferTime = ev.xproperty.time;
|
||||
} else {
|
||||
std::list<TXWindow*>::iterator i;
|
||||
for (i = windows.begin(); i != windows.end(); i++) {
|
||||
if ((*i)->win() == ev.xany.window)
|
||||
(*i)->handleXEvent(&ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TXGlobalEventHandler* TXWindow::setGlobalEventHandler(TXGlobalEventHandler* h)
|
||||
{
|
||||
TXGlobalEventHandler* old = globalEventHandler;
|
||||
globalEventHandler = h;
|
||||
return old;
|
||||
}
|
||||
|
||||
void TXWindow::getColours(Display* dpy, XColor* cols, int nCols)
|
||||
{
|
||||
bool* got = new bool[nCols];
|
||||
bool failed = false;
|
||||
int i;
|
||||
for (i = 0; i < nCols; i++) {
|
||||
if (XAllocColor(dpy, cmap, &cols[i])) {
|
||||
got[i] = true;
|
||||
} else {
|
||||
got[i] = false;
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
delete [] got;
|
||||
return;
|
||||
}
|
||||
|
||||
// AllocColor has failed. This is because the colormap is full. So the
|
||||
// only thing we can do is use the "shared" pixels in the colormap. The
|
||||
// code below is designed to work even when the colormap isn't full so is
|
||||
// more complex than it needs to be in this case. However it would be
|
||||
// useful one day to be able to restrict the number of colours allocated by
|
||||
// an application so I'm leaving it in here.
|
||||
|
||||
// For each pixel in the colormap, try to allocate exactly its RGB values.
|
||||
// If this returns a different pixel then it must be a private or
|
||||
// unallocated pixel, so we can't use it. If it returns us the same pixel
|
||||
// again, it's almost certainly a shared colour, so we can use it (actually
|
||||
// it is possible that it was an unallocated pixel which we've now
|
||||
// allocated - by going through the pixels in reverse order we make this
|
||||
// unlikely except for the lowest unallocated pixel - this works because of
|
||||
// the way the X server allocates new pixels).
|
||||
|
||||
int cmapSize = DisplayCells(dpy,DefaultScreen(dpy));
|
||||
|
||||
XColor* cm = new XColor[cmapSize];
|
||||
bool* shared = new bool[cmapSize];
|
||||
bool* usedAsNearest = new bool[cmapSize];
|
||||
|
||||
for (i = 0; i < cmapSize; i++) {
|
||||
cm[i].pixel = i;
|
||||
shared[i] = usedAsNearest[i] = false;
|
||||
}
|
||||
|
||||
XQueryColors(dpy, cmap, cm, cmapSize);
|
||||
|
||||
for (i = cmapSize-1; i >= 0; i--) {
|
||||
if (XAllocColor(dpy, cmap, &cm[i])) {
|
||||
if (cm[i].pixel == (unsigned long)i) {
|
||||
shared[i] = true;
|
||||
} else {
|
||||
XFreeColors(dpy, cmap, &cm[i].pixel, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < nCols; j++) {
|
||||
unsigned long minDistance = ULONG_MAX;
|
||||
unsigned long nearestPixel = 0;
|
||||
if (!got[j]) {
|
||||
for (i = 0; i < cmapSize; i++) {
|
||||
if (shared[i]) {
|
||||
unsigned long rd = (cm[i].red - cols[j].red)/2;
|
||||
unsigned long gd = (cm[i].green - cols[j].green)/2;
|
||||
unsigned long bd = (cm[i].blue - cols[j].blue)/2;
|
||||
unsigned long distance = (rd*rd + gd*gd + bd*bd);
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
nearestPixel = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cols[j].pixel = nearestPixel;
|
||||
usedAsNearest[nearestPixel] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cmapSize; i++) {
|
||||
if (shared[i] && !usedAsNearest[i]) {
|
||||
unsigned long p = i;
|
||||
XFreeColors(dpy, cmap, &p, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Window TXWindow::windowWithName(Display* dpy, Window top, const char* name)
|
||||
{
|
||||
char* windowName;
|
||||
if (XFetchName(dpy, top, &windowName)) {
|
||||
if (strcmp(windowName, name) == 0) {
|
||||
XFree(windowName);
|
||||
return top;
|
||||
}
|
||||
XFree(windowName);
|
||||
}
|
||||
|
||||
Window* children;
|
||||
Window dummy;
|
||||
unsigned int nchildren;
|
||||
if (!XQueryTree(dpy, top, &dummy, &dummy, &children,&nchildren) || !children)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < (int)nchildren; i++) {
|
||||
Window w = windowWithName(dpy, children[i], name);
|
||||
if (w) {
|
||||
XFree((char*)children);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
XFree((char*)children);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TXWindow::TXWindow(Display* dpy_, int w, int h, TXWindow* parent_,
|
||||
int borderWidth)
|
||||
: dpy(dpy_), xPad(3), yPad(3), bevel(2), parent(parent_), width_(w),
|
||||
height_(h), eventHandler(0), dwc(0), eventMask(0), toplevel_(false)
|
||||
{
|
||||
sizeHints.flags = 0;
|
||||
XSetWindowAttributes attr;
|
||||
attr.background_pixel = defaultBg;
|
||||
attr.border_pixel = 0;
|
||||
Window par = parent ? parent->win() : DefaultRootWindow(dpy);
|
||||
win_ = XCreateWindow(dpy, par, 0, 0, width_, height_, borderWidth,
|
||||
CopyFromParent, CopyFromParent, CopyFromParent,
|
||||
CWBackPixel | CWBorderPixel, &attr);
|
||||
if (parent) map();
|
||||
|
||||
windows.push_back(this);
|
||||
}
|
||||
|
||||
TXWindow::~TXWindow()
|
||||
{
|
||||
windows.remove(this);
|
||||
XDestroyWindow(dpy, win());
|
||||
}
|
||||
|
||||
void TXWindow::toplevel(const char* name, TXDeleteWindowCallback* dwc_,
|
||||
int argc, char** argv, const char* windowClass,
|
||||
bool iconic)
|
||||
{
|
||||
toplevel_ = true;
|
||||
XWMHints wmHints;
|
||||
wmHints.flags = InputHint|StateHint;
|
||||
wmHints.input = True;
|
||||
wmHints.initial_state = iconic ? IconicState : NormalState;
|
||||
XClassHint classHint;
|
||||
if (!windowClass) windowClass = defaultWindowClass;
|
||||
classHint.res_name = (char*)name;
|
||||
classHint.res_class = (char*)windowClass;
|
||||
XSetWMProperties(dpy, win(), 0, 0, argv, argc,
|
||||
&sizeHints, &wmHints, &classHint);
|
||||
XStoreName(dpy, win(), name);
|
||||
XSetIconName(dpy, win(), name);
|
||||
Atom protocols[10];
|
||||
int nProtocols = 0;
|
||||
protocols[nProtocols++] = wmTakeFocus;
|
||||
dwc = dwc_;
|
||||
if (dwc)
|
||||
protocols[nProtocols++] = wmDeleteWindow;
|
||||
XSetWMProtocols(dpy, win(), protocols, nProtocols);
|
||||
addEventMask(StructureNotifyMask);
|
||||
}
|
||||
|
||||
void TXWindow::setName(const char* name)
|
||||
{
|
||||
XClassHint classHint;
|
||||
XGetClassHint(dpy, win(), &classHint);
|
||||
XFree(classHint.res_name);
|
||||
classHint.res_name = (char*)name;
|
||||
XSetClassHint(dpy, win(), &classHint);
|
||||
XFree(classHint.res_class);
|
||||
XStoreName(dpy, win(), name);
|
||||
XSetIconName(dpy, win(), name);
|
||||
}
|
||||
|
||||
void TXWindow::setMaxSize(int w, int h)
|
||||
{
|
||||
sizeHints.flags |= PMaxSize;
|
||||
sizeHints.max_width = w;
|
||||
sizeHints.max_height = h;
|
||||
XSetWMNormalHints(dpy, win(), &sizeHints);
|
||||
}
|
||||
|
||||
void TXWindow::setUSPosition(int x, int y)
|
||||
{
|
||||
sizeHints.flags |= USPosition;
|
||||
sizeHints.x = x;
|
||||
sizeHints.y = y;
|
||||
XSetWMNormalHints(dpy, win(), &sizeHints);
|
||||
move(x, y);
|
||||
}
|
||||
|
||||
void TXWindow::setGeometry(const char* geom, int x, int y, int w, int h)
|
||||
{
|
||||
char defGeom[256];
|
||||
sprintf(defGeom,"%dx%d+%d+%d",w,h,x,y);
|
||||
XWMGeometry(dpy, DefaultScreen(dpy), strEmptyToNull((char*)geom), defGeom,
|
||||
0, &sizeHints, &x, &y, &w, &h, &sizeHints.win_gravity);
|
||||
sizeHints.flags |= PWinGravity;
|
||||
setUSPosition(x, y);
|
||||
resize(w, h);
|
||||
}
|
||||
|
||||
TXEventHandler* TXWindow::setEventHandler(TXEventHandler* h)
|
||||
{
|
||||
TXEventHandler* old = eventHandler;
|
||||
eventHandler = h;
|
||||
return old;
|
||||
}
|
||||
|
||||
void TXWindow::addEventMask(long mask)
|
||||
{
|
||||
eventMask |= mask;
|
||||
XSelectInput(dpy, win(), eventMask);
|
||||
}
|
||||
|
||||
void TXWindow::removeEventMask(long mask)
|
||||
{
|
||||
eventMask &= ~mask;
|
||||
XSelectInput(dpy, win(), eventMask);
|
||||
}
|
||||
|
||||
void TXWindow::unmap()
|
||||
{
|
||||
XUnmapWindow(dpy, win());
|
||||
if (toplevel_) {
|
||||
XUnmapEvent ue;
|
||||
ue.type = UnmapNotify;
|
||||
ue.display = dpy;
|
||||
ue.event = DefaultRootWindow(dpy);
|
||||
ue.window = win();
|
||||
ue.from_configure = False;
|
||||
XSendEvent(dpy, DefaultRootWindow(dpy), False,
|
||||
(SubstructureRedirectMask|SubstructureNotifyMask),
|
||||
(XEvent*)&ue);
|
||||
}
|
||||
}
|
||||
|
||||
void TXWindow::resize(int w, int h)
|
||||
{
|
||||
//if (w == width_ && h == height_) return;
|
||||
XResizeWindow(dpy, win(), w, h);
|
||||
width_ = w;
|
||||
height_ = h;
|
||||
resizeNotify();
|
||||
}
|
||||
|
||||
void TXWindow::setBorderWidth(int bw)
|
||||
{
|
||||
XWindowChanges c;
|
||||
c.border_width = bw;
|
||||
XConfigureWindow(dpy, win(), CWBorderWidth, &c);
|
||||
}
|
||||
|
||||
void TXWindow::ownSelection(Atom selection, Time time)
|
||||
{
|
||||
XSetSelectionOwner(dpy, selection, win(), time);
|
||||
if (XGetSelectionOwner(dpy, selection) == win()) {
|
||||
selectionOwner_[selection] = true;
|
||||
selectionOwnTime[selection] = time;
|
||||
}
|
||||
}
|
||||
|
||||
void TXWindow::handleXEvent(XEvent* ev)
|
||||
{
|
||||
switch (ev->type) {
|
||||
|
||||
case ClientMessage:
|
||||
if (ev->xclient.message_type == wmProtocols) {
|
||||
if ((Atom)ev->xclient.data.l[0] == wmDeleteWindow) {
|
||||
if (dwc) dwc->deleteWindow(this);
|
||||
} else if ((Atom)ev->xclient.data.l[0] == wmTakeFocus) {
|
||||
takeFocus(ev->xclient.data.l[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
if (ev->xconfigure.width != width_ || ev->xconfigure.height != height_) {
|
||||
width_ = ev->xconfigure.width;
|
||||
height_ = ev->xconfigure.height;
|
||||
resizeNotify();
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectionNotify:
|
||||
if (ev->xselection.property != None) {
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitems, after;
|
||||
unsigned char *data;
|
||||
XGetWindowProperty(dpy, win(), ev->xselection.property, 0, 16384, True,
|
||||
AnyPropertyType, &type, &format,
|
||||
&nitems, &after, &data);
|
||||
if (type != None) {
|
||||
selectionNotify(&ev->xselection, type, format, nitems, data);
|
||||
XFree(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
selectionNotify(&ev->xselection, 0, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case SelectionRequest:
|
||||
{
|
||||
XSelectionEvent se;
|
||||
se.type = SelectionNotify;
|
||||
se.display = ev->xselectionrequest.display;
|
||||
se.requestor = ev->xselectionrequest.requestor;
|
||||
se.selection = ev->xselectionrequest.selection;
|
||||
se.time = ev->xselectionrequest.time;
|
||||
se.target = ev->xselectionrequest.target;
|
||||
if (ev->xselectionrequest.property == None)
|
||||
ev->xselectionrequest.property = ev->xselectionrequest.target;
|
||||
if (!selectionOwner_[se.selection]) {
|
||||
se.property = None;
|
||||
} else {
|
||||
se.property = ev->xselectionrequest.property;
|
||||
if (se.target == xaTARGETS) {
|
||||
Atom targets[2];
|
||||
targets[0] = xaTIMESTAMP;
|
||||
targets[1] = XA_STRING;
|
||||
XChangeProperty(dpy, se.requestor, se.property, XA_ATOM, 32,
|
||||
PropModeReplace, (unsigned char*)targets, 2);
|
||||
} else if (se.target == xaTIMESTAMP) {
|
||||
rdr::U32 t = selectionOwnTime[se.selection];
|
||||
XChangeProperty(dpy, se.requestor, se.property, XA_INTEGER, 32,
|
||||
PropModeReplace, (unsigned char*)&t, 1);
|
||||
} else if (se.target == XA_STRING) {
|
||||
if (!selectionRequest(se.requestor, se.selection, se.property))
|
||||
se.property = None;
|
||||
} else {
|
||||
se.property = None;
|
||||
}
|
||||
}
|
||||
XSendEvent(dpy, se.requestor, False, 0, (XEvent*)&se);
|
||||
break;
|
||||
}
|
||||
|
||||
case SelectionClear:
|
||||
selectionOwner_[ev->xselectionclear.selection] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (eventHandler) eventHandler->handleEvent(this, ev);
|
||||
}
|
||||
|
||||
void TXWindow::drawBevel(GC gc, int x, int y, int w, int h, int b,
|
||||
unsigned long middle, unsigned long tl,
|
||||
unsigned long br, bool round)
|
||||
{
|
||||
if (round) {
|
||||
XGCValues gcv;
|
||||
gcv.line_width = b;
|
||||
XChangeGC(dpy, gc, GCLineWidth, &gcv);
|
||||
XSetForeground(dpy, gc, middle);
|
||||
XFillArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 0, 360*64);
|
||||
XSetForeground(dpy, gc, tl);
|
||||
XDrawArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 45*64, 180*64);
|
||||
XSetForeground(dpy, gc, br);
|
||||
XDrawArc(dpy, win(), gc, x, y, w-b/2, h-b/2, 225*64, 180*64);
|
||||
} else {
|
||||
XSetForeground(dpy, gc, middle);
|
||||
if (w-2*b > 0 && h-2*b > 0)
|
||||
XFillRectangle(dpy, win(), gc, x+b, y+b, w-2*b, h-2*b);
|
||||
XSetForeground(dpy, gc, tl);
|
||||
XFillRectangle(dpy, win(), gc, x, y, w, b);
|
||||
XFillRectangle(dpy, win(), gc, x, y, b, h);
|
||||
XSetForeground(dpy, gc, br);
|
||||
for (int i = 0; i < b; i++) {
|
||||
if (w-i > 0) XFillRectangle(dpy, win(), gc, x+i, y+h-1-i, w-i, 1);
|
||||
if (h-1-i > 0) XFillRectangle(dpy, win(), gc, x+w-1-i, y+i+1, 1, h-1-i);
|
||||
}
|
||||
}
|
||||
}
|
||||
228
unix/tx/TXWindow.h
Normal file
228
unix/tx/TXWindow.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// TXWindow.h
|
||||
//
|
||||
// A TXWindow is the base class for all tx windows (widgets). In addition it
|
||||
// contains a number of static methods and members which are used throughout
|
||||
// tx.
|
||||
//
|
||||
// Before calling any other tx methods, TXWindow::init() must be called with
|
||||
// the X display to use.
|
||||
|
||||
#ifndef __TXWINDOW_H__
|
||||
#define __TXWINDOW_H__
|
||||
|
||||
#include <rdr/types.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <map>
|
||||
|
||||
|
||||
// TXDeleteWindowCallback's deleteWindow() method is called when a top-level
|
||||
// window is "deleted" (closed) by the user using the window manager.
|
||||
class TXWindow;
|
||||
class TXDeleteWindowCallback {
|
||||
public:
|
||||
virtual void deleteWindow(TXWindow* w) = 0;
|
||||
};
|
||||
|
||||
// TXEventHandler is an interface implemented by classes wanting to handle X
|
||||
// events on a window. Most derived classes of window are their own event
|
||||
// handlers.
|
||||
class TXEventHandler {
|
||||
public:
|
||||
virtual void handleEvent(TXWindow* w, XEvent* ev) = 0;
|
||||
};
|
||||
|
||||
// TXGlobalEventHandler is similar to TXEventHandler but will be called early and
|
||||
// for every X event. The handler should return true to indicate that the
|
||||
// event was swallowed and shouldn't be processed further.
|
||||
class TXGlobalEventHandler {
|
||||
public:
|
||||
virtual bool handleGlobalEvent(XEvent* ev) = 0;
|
||||
};
|
||||
|
||||
class TXWindow {
|
||||
public:
|
||||
|
||||
// Constructor - creates a window of the given size, with the default
|
||||
// background (currently grey). It is mapped by default if it has a parent.
|
||||
// If no parent is specified its parent is the root window and it will remain
|
||||
// unmapped.
|
||||
TXWindow(Display* dpy_, int width=1, int height=1, TXWindow* parent_=0,
|
||||
int borderWidth=0);
|
||||
virtual ~TXWindow();
|
||||
|
||||
// toplevel() declares that this is a top-level window. Various
|
||||
// window-manager-related properties are set on the window. The given
|
||||
// TXDeleteWindowCallback is notified when the window is "deleted" (cloesd)
|
||||
// by the user.
|
||||
void toplevel(const char* name, TXDeleteWindowCallback* dwc=0,
|
||||
int argc=0, char** argv=0, const char* windowClass=0,
|
||||
bool iconic=false);
|
||||
|
||||
// setMaxSize() tells the window manager the maximum size to allow a
|
||||
// top-level window. It has no effect on a non-top-level window.
|
||||
void setMaxSize(int w, int h);
|
||||
|
||||
// setUSPosition() tells the window manager the position which the "user" has
|
||||
// asked for a top-level window. Most window managers ignore requests by a
|
||||
// program for position, so you have to tell it that the "user" asked for the
|
||||
// position. This has no effect on a non-top-level window.
|
||||
void setUSPosition(int x, int y);
|
||||
|
||||
void setGeometry(const char* geom, int x, int y, int w, int h);
|
||||
|
||||
void setName(const char* name);
|
||||
|
||||
// setTransientFor() tells the window manager that this window is "owned" by
|
||||
// the given window. The window manager can use this information as it sees
|
||||
// fit.
|
||||
void setTransientFor(Window w) { XSetTransientForHint(dpy, win(), w); }
|
||||
|
||||
// setEventHandler() sets the TXEventHandler to handle X events for this
|
||||
// window. It returns the previous event handler, so that handlers can chain
|
||||
// themselves.
|
||||
TXEventHandler* setEventHandler(TXEventHandler* h);
|
||||
|
||||
// Accessor methods
|
||||
Window win() { return win_; }
|
||||
int width() { return width_; }
|
||||
int height() { return height_; }
|
||||
|
||||
// selectionOwner() returns true if this window owns the given selection.
|
||||
bool selectionOwner(Atom selection) { return selectionOwner_[selection]; }
|
||||
|
||||
// Wrappers around common Xlib calls
|
||||
void addEventMask(long mask);
|
||||
void removeEventMask(long mask);
|
||||
void map() { XMapWindow(dpy, win()); }
|
||||
void unmap();
|
||||
void setBg(unsigned long bg) { XSetWindowBackground(dpy, win(), bg); }
|
||||
void move(int x, int y) { XMoveWindow(dpy, win(), x, y); }
|
||||
void resize(int w, int h);
|
||||
void raise() { XRaiseWindow(dpy, win()); }
|
||||
void setBorderWidth(int bw);
|
||||
void invalidate(int x=0, int y=0, int w=0, int h=0) { XClearArea(dpy, win(), x, y, w, h, True); }
|
||||
|
||||
// ownSelection requests that the window owns the given selection from the
|
||||
// given time (the time should be taken from an X event).
|
||||
void ownSelection(Atom selection, Time time);
|
||||
|
||||
|
||||
// drawBevel draws a rectangular or circular bevel filling the given
|
||||
// rectangle, using the given colours for the middle, the top/left and the
|
||||
// bottom/right.
|
||||
void drawBevel(GC gc, int x, int y, int w, int h, int b,
|
||||
unsigned long middle, unsigned long tl, unsigned long br,
|
||||
bool round=false);
|
||||
|
||||
// Methods to be overridden in a derived class
|
||||
|
||||
// resizeNotify() is called whenever the window's dimensions may have
|
||||
// changed.
|
||||
virtual void resizeNotify() {}
|
||||
|
||||
// takeFocus() is called when the window has received keyboard focus from the
|
||||
// window manager.
|
||||
virtual void takeFocus(Time time) {}
|
||||
|
||||
// selectionNotify() is called when the selection owner has replied to a
|
||||
// request for information about a selection from the selection owner.
|
||||
virtual void selectionNotify(XSelectionEvent* ev, Atom type, int format,
|
||||
int nitems, void* data) {}
|
||||
|
||||
// selectionRequest() is called when this window is the selection owner and
|
||||
// another X client has requested the selection. It should set the given
|
||||
// property on the given window to the value of the given selection,
|
||||
// returning true if successful, false otherwise.
|
||||
virtual bool selectionRequest(Window requestor,
|
||||
Atom selection, Atom property) { return false;}
|
||||
|
||||
// Static methods
|
||||
|
||||
// init() must be called before any other tx methods.
|
||||
static void init(Display* dpy, const char* defaultWindowClass);
|
||||
|
||||
// getColours() sets the pixel values in the cols array to the best available
|
||||
// for the given rgb values, even in the case of a full colormap.
|
||||
static void getColours(Display* dpy, XColor* cols, int nCols);
|
||||
|
||||
// handleXEvents() should be called whenever there are events to handle on
|
||||
// the connection to the X display. It process all available events, then
|
||||
// returns when there are no more events to process.
|
||||
static void handleXEvents(Display* dpy);
|
||||
|
||||
// setGlobalEventHandler() sets the TXGlobalEventHandler to intercept all
|
||||
// X events. It returns the previous events handler, so that handlers can
|
||||
// chain themselves.
|
||||
static TXGlobalEventHandler* setGlobalEventHandler(TXGlobalEventHandler* h);
|
||||
|
||||
// windowWithName() locates a window with a given name on a display.
|
||||
static Window windowWithName(Display* dpy, Window top, const char* name);
|
||||
|
||||
// strEmptyToNull() returns the string it's given but turns an empty string
|
||||
// into null, which can be useful for passing rfb parameters to Xlib calls.
|
||||
static char* strEmptyToNull(char* s) { return s && s[0] ? s : 0; }
|
||||
|
||||
// The following are default values for various things.
|
||||
static unsigned long black, white;
|
||||
static unsigned long defaultFg, defaultBg, lightBg, darkBg;
|
||||
static unsigned long disabledFg, disabledBg, enabledBg;
|
||||
static unsigned long scrollbarBg;
|
||||
static GC defaultGC;
|
||||
static Colormap cmap;
|
||||
static Font defaultFont;
|
||||
static XFontStruct* defaultFS;
|
||||
static Time cutBufferTime;
|
||||
static Pixmap dot, tick;
|
||||
static const int dotSize, tickSize;
|
||||
static char* defaultWindowClass;
|
||||
|
||||
Display* const dpy;
|
||||
|
||||
int xPad, yPad, bevel;
|
||||
|
||||
private:
|
||||
|
||||
// handleXEvent() is called from handleXEvents() when an event for this
|
||||
// window arrives. It does general event processing before calling on to the
|
||||
// event handler.
|
||||
void handleXEvent(XEvent* ev);
|
||||
|
||||
TXWindow* parent;
|
||||
Window win_;
|
||||
int width_, height_;
|
||||
TXEventHandler* eventHandler;
|
||||
TXDeleteWindowCallback* dwc;
|
||||
long eventMask;
|
||||
XSizeHints sizeHints;
|
||||
std::map<Atom,Time> selectionOwnTime;
|
||||
std::map<Atom,bool> selectionOwner_;
|
||||
bool toplevel_;
|
||||
|
||||
static TXGlobalEventHandler* globalEventHandler;
|
||||
};
|
||||
|
||||
extern Atom wmProtocols, wmDeleteWindow, wmTakeFocus;
|
||||
extern Atom xaTIMESTAMP, xaTARGETS, xaSELECTION_TIME, xaSELECTION_STRING;
|
||||
extern Atom xaCLIPBOARD;
|
||||
|
||||
#endif
|
||||
1
unix/vncconfig/.gitignore
vendored
Normal file
1
unix/vncconfig/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
vncconfig
|
||||
15
unix/vncconfig/CMakeLists.txt
Normal file
15
unix/vncconfig/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/unix/tx)
|
||||
|
||||
add_executable(vncconfig
|
||||
buildtime.c
|
||||
vncExt.c
|
||||
vncconfig.cxx
|
||||
QueryConnectDialog.cxx)
|
||||
|
||||
target_link_libraries(vncconfig tx rfb network rdr ${X11_LIBRARIES})
|
||||
|
||||
install(TARGETS vncconfig DESTINATION ${BIN_DIR})
|
||||
install(FILES vncconfig.man DESTINATION ${MAN_DIR}/man1 RENAME vncconfig.1)
|
||||
88
unix/vncconfig/QueryConnectDialog.cxx
Normal file
88
unix/vncconfig/QueryConnectDialog.cxx
Normal file
@@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rdr/Exception.h>
|
||||
#include "QueryConnectDialog.h"
|
||||
#include "vncExt.h"
|
||||
|
||||
QueryConnectDialog::QueryConnectDialog(Display* dpy,
|
||||
const char* address_,
|
||||
const char* user_,
|
||||
int timeout_,
|
||||
QueryResultCallback* cb)
|
||||
: TXDialog(dpy, 300, 100, "VNC Server : Accept Connection?"),
|
||||
addressLbl(dpy, "Host:",this),
|
||||
address(dpy, address_, this),
|
||||
userLbl(dpy, "User:", this),
|
||||
user(dpy, user_, this),
|
||||
timeoutLbl(dpy, "Seconds until automatic reject:", this),
|
||||
timeout(dpy, "0000000000", this),
|
||||
accept(dpy, "Accept", this, this, 60),
|
||||
reject(dpy, "Reject", this, this, 60),
|
||||
callback(cb), timeUntilReject(timeout_), timer(this)
|
||||
{
|
||||
const int pad = 4;
|
||||
int y=pad;
|
||||
int lblWidth = __rfbmax(addressLbl.width(), userLbl.width());
|
||||
userLbl.move(pad+lblWidth-userLbl.width(), y);
|
||||
user.move(pad+lblWidth, y);
|
||||
addressLbl.move(pad+lblWidth-addressLbl.width(), y+=userLbl.height());
|
||||
address.move(pad+lblWidth, y);
|
||||
timeoutLbl.move(pad, y+=addressLbl.height());
|
||||
timeout.move(pad+timeoutLbl.width(), y);
|
||||
accept.move(pad, y+=addressLbl.height());
|
||||
int maxWidth = __rfbmax(user.width(), address.width()+pad+lblWidth);
|
||||
maxWidth = __rfbmax(maxWidth, accept.width()*3);
|
||||
maxWidth = __rfbmax(maxWidth, timeoutLbl.width()+timeout.width()+pad);
|
||||
reject.move(maxWidth-reject.width(), y);
|
||||
resize(maxWidth + pad, y+reject.height()+pad);
|
||||
setBorderWidth(1);
|
||||
refreshTimeout();
|
||||
timer.start(1000);
|
||||
}
|
||||
|
||||
void QueryConnectDialog::deleteWindow(TXWindow*) {
|
||||
unmap();
|
||||
callback->queryRejected();
|
||||
}
|
||||
|
||||
void QueryConnectDialog::buttonActivate(TXButton* b) {
|
||||
unmap();
|
||||
if (b == &accept)
|
||||
callback->queryApproved();
|
||||
else if (b == &reject)
|
||||
callback->queryRejected();
|
||||
}
|
||||
|
||||
bool QueryConnectDialog::handleTimeout(rfb::Timer* t) {
|
||||
if (timeUntilReject-- == 0) {
|
||||
unmap();
|
||||
callback->queryTimedOut();
|
||||
return false;
|
||||
} else {
|
||||
refreshTimeout();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void QueryConnectDialog::refreshTimeout() {
|
||||
char buf[16];
|
||||
sprintf(buf, "%d", timeUntilReject);
|
||||
timeout.setText(buf);
|
||||
}
|
||||
56
unix/vncconfig/QueryConnectDialog.h
Normal file
56
unix/vncconfig/QueryConnectDialog.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef __QUERYCONNECTDIALOG_H__
|
||||
#define __QUERYCONNECTDIALOG_H__
|
||||
|
||||
#include <rfb/Timer.h>
|
||||
#include "TXLabel.h"
|
||||
#include "TXButton.h"
|
||||
#include "TXDialog.h"
|
||||
|
||||
class QueryResultCallback {
|
||||
public:
|
||||
virtual ~QueryResultCallback() {}
|
||||
virtual void queryApproved() = 0;
|
||||
virtual void queryRejected() = 0;
|
||||
virtual void queryTimedOut() { queryRejected(); };
|
||||
};
|
||||
|
||||
class QueryConnectDialog : public TXDialog, public TXEventHandler,
|
||||
public TXButtonCallback,
|
||||
public rfb::Timer::Callback
|
||||
{
|
||||
public:
|
||||
QueryConnectDialog(Display* dpy, const char* address_,
|
||||
const char* user_, int timeout_,
|
||||
QueryResultCallback* cb);
|
||||
void handleEvent(TXWindow*, XEvent* ) { }
|
||||
void deleteWindow(TXWindow*);
|
||||
void buttonActivate(TXButton* b);
|
||||
bool handleTimeout(rfb::Timer* t);
|
||||
private:
|
||||
void refreshTimeout();
|
||||
TXLabel addressLbl, address, userLbl, user, timeoutLbl, timeout;
|
||||
TXButton accept, reject;
|
||||
QueryResultCallback* callback;
|
||||
int timeUntilReject;
|
||||
rfb::Timer timer;
|
||||
};
|
||||
|
||||
#endif
|
||||
18
unix/vncconfig/buildtime.c
Normal file
18
unix/vncconfig/buildtime.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
char buildtime[] = __DATE__ " " __TIME__;
|
||||
319
unix/vncconfig/vncExt.c
Normal file
319
unix/vncconfig/vncExt.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define NEED_REPLIES
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#define _VNCEXT_PROTO_
|
||||
#include "vncExt.h"
|
||||
|
||||
static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
|
||||
xEvent* w);
|
||||
|
||||
static Bool extensionInited = False;
|
||||
static XExtCodes* codes = 0;
|
||||
|
||||
static Bool checkExtension(Display* dpy)
|
||||
{
|
||||
if (!extensionInited) {
|
||||
extensionInited = True;
|
||||
codes = XInitExtension(dpy, VNCEXTNAME);
|
||||
if (!codes) return False;
|
||||
XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify,
|
||||
XVncExtQueryConnectNotifyWireToEvent);
|
||||
}
|
||||
return codes != 0;
|
||||
}
|
||||
|
||||
Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
|
||||
{
|
||||
if (!checkExtension(dpy)) return False;
|
||||
*event_basep = codes->first_event;
|
||||
*error_basep = codes->first_error;
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool XVncExtSetParam(Display* dpy, const char* param)
|
||||
{
|
||||
xVncExtSetParamReq* req;
|
||||
xVncExtSetParamReply rep;
|
||||
|
||||
int paramLen = strlen(param);
|
||||
if (paramLen > 255) return False;
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtSetParam, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtSetParam;
|
||||
req->length += (paramLen + 3) >> 2;
|
||||
req->paramLen = paramLen;
|
||||
Data(dpy, param, paramLen);
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return rep.success;
|
||||
}
|
||||
|
||||
Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
|
||||
{
|
||||
xVncExtGetParamReq* req;
|
||||
xVncExtGetParamReply rep;
|
||||
|
||||
int paramLen = strlen(param);
|
||||
*value = 0;
|
||||
*len = 0;
|
||||
if (paramLen > 255) return False;
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtGetParam, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtGetParam;
|
||||
req->length += (paramLen + 3) >> 2;
|
||||
req->paramLen = paramLen;
|
||||
Data(dpy, param, paramLen);
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
if (rep.success) {
|
||||
*len = rep.valueLen;
|
||||
*value = (char*) Xmalloc (*len+1);
|
||||
if (!*value) {
|
||||
_XEatData(dpy, (*len+1)&~1);
|
||||
return False;
|
||||
}
|
||||
_XReadPad(dpy, *value, *len);
|
||||
(*value)[*len] = 0;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return rep.success;
|
||||
}
|
||||
|
||||
char* XVncExtGetParamDesc(Display* dpy, const char* param)
|
||||
{
|
||||
xVncExtGetParamDescReq* req;
|
||||
xVncExtGetParamDescReply rep;
|
||||
char* desc = 0;
|
||||
|
||||
int paramLen = strlen(param);
|
||||
if (paramLen > 255) return False;
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtGetParamDesc, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtGetParamDesc;
|
||||
req->length += (paramLen + 3) >> 2;
|
||||
req->paramLen = paramLen;
|
||||
Data(dpy, param, paramLen);
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
if (rep.success) {
|
||||
desc = (char*)Xmalloc(rep.descLen+1);
|
||||
if (!desc) {
|
||||
_XEatData(dpy, (rep.descLen+1)&~1);
|
||||
return False;
|
||||
}
|
||||
_XReadPad(dpy, desc, rep.descLen);
|
||||
desc[rep.descLen] = 0;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return desc;
|
||||
}
|
||||
|
||||
char** XVncExtListParams(Display* dpy, int* nParams)
|
||||
{
|
||||
xVncExtListParamsReq* req;
|
||||
xVncExtListParamsReply rep;
|
||||
char** list = 0;
|
||||
char* ch;
|
||||
int rlen, paramLen, i;
|
||||
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtListParams, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtListParams;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
if (rep.nParams) {
|
||||
list = (char**)Xmalloc(rep.nParams * sizeof(char*));
|
||||
rlen = rep.length << 2;
|
||||
ch = (char*)Xmalloc(rlen + 1);
|
||||
if (!list || !ch) {
|
||||
if (list) Xfree((char*)list);
|
||||
if (ch) Xfree(ch);
|
||||
_XEatData(dpy, rlen);
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return 0;
|
||||
}
|
||||
_XReadPad(dpy, ch, rlen);
|
||||
paramLen = *ch++;
|
||||
for (i = 0; i < rep.nParams; i++) {
|
||||
list[i] = ch;
|
||||
ch += paramLen;
|
||||
paramLen = *ch;
|
||||
*ch++ = 0;
|
||||
}
|
||||
}
|
||||
*nParams = rep.nParams;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return list;
|
||||
}
|
||||
|
||||
void XVncExtFreeParamList(char** list)
|
||||
{
|
||||
if (list) {
|
||||
Xfree(list[0]-1);
|
||||
Xfree((char*)list);
|
||||
}
|
||||
}
|
||||
|
||||
Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
|
||||
{
|
||||
xVncExtSelectInputReq* req;
|
||||
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtSelectInput, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtSelectInput;
|
||||
req->window = w;
|
||||
req->mask = mask;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool XVncExtConnect(Display* dpy, const char* hostAndPort)
|
||||
{
|
||||
xVncExtConnectReq* req;
|
||||
xVncExtConnectReply rep;
|
||||
|
||||
int strLen = strlen(hostAndPort);
|
||||
if (strLen > 255) return False;
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtConnect, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtConnect;
|
||||
req->length += (strLen + 3) >> 2;
|
||||
req->strLen = strLen;
|
||||
Data(dpy, hostAndPort, strLen);
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return rep.success;
|
||||
}
|
||||
|
||||
Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user,
|
||||
int* timeout, void** opaqueId)
|
||||
{
|
||||
xVncExtGetQueryConnectReq* req;
|
||||
xVncExtGetQueryConnectReply rep;
|
||||
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtGetQueryConnect, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtGetQueryConnect;
|
||||
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return False;
|
||||
}
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
|
||||
*addr = Xmalloc(rep.addrLen+1);
|
||||
*user = Xmalloc(rep.userLen+1);
|
||||
if (!*addr || !*user) {
|
||||
Xfree(*addr);
|
||||
Xfree(*user);
|
||||
_XEatData(dpy, ((rep.addrLen+1)&~1) + ((rep.userLen+1)&~1));
|
||||
return False;
|
||||
}
|
||||
_XReadPad(dpy, *addr, rep.addrLen);
|
||||
(*addr)[rep.addrLen] = 0;
|
||||
_XReadPad(dpy, *user, rep.userLen);
|
||||
(*user)[rep.userLen] = 0;
|
||||
*timeout = rep.timeout;
|
||||
*opaqueId = (void*)(intptr_t)rep.opaqueId;
|
||||
return True;
|
||||
}
|
||||
|
||||
Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve)
|
||||
{
|
||||
xVncExtApproveConnectReq* req;
|
||||
|
||||
if (!checkExtension(dpy)) return False;
|
||||
|
||||
LockDisplay(dpy);
|
||||
GetReq(VncExtApproveConnect, req);
|
||||
req->reqType = codes->major_opcode;
|
||||
req->vncExtReqType = X_VncExtApproveConnect;
|
||||
req->approve = approve;
|
||||
req->opaqueId = (CARD32)(intptr_t)opaqueId;
|
||||
UnlockDisplay(dpy);
|
||||
SyncHandle();
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
|
||||
xEvent* w)
|
||||
{
|
||||
XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e;
|
||||
xVncExtQueryConnectNotifyEvent* wire
|
||||
= (xVncExtQueryConnectNotifyEvent*)w;
|
||||
ev->type = wire->type & 0x7f;
|
||||
ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
|
||||
ev->send_event = (wire->type & 0x80) != 0;
|
||||
ev->display = dpy;
|
||||
ev->window = wire->window;
|
||||
return True;
|
||||
}
|
||||
258
unix/vncconfig/vncExt.h
Normal file
258
unix/vncconfig/vncExt.h
Normal file
@@ -0,0 +1,258 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#ifndef _VNCEXT_H_
|
||||
#define _VNCEXT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define X_VncExtSetParam 0
|
||||
#define X_VncExtGetParam 1
|
||||
#define X_VncExtGetParamDesc 2
|
||||
#define X_VncExtListParams 3
|
||||
#define X_VncExtSelectInput 6
|
||||
#define X_VncExtConnect 7
|
||||
#define X_VncExtGetQueryConnect 8
|
||||
#define X_VncExtApproveConnect 9
|
||||
|
||||
#define VncExtQueryConnectNotify 2
|
||||
#define VncExtQueryConnectMask (1 << VncExtQueryConnectNotify)
|
||||
|
||||
#define VncExtNumberEvents 3
|
||||
#define VncExtNumberErrors 0
|
||||
|
||||
#ifndef _VNCEXT_SERVER_
|
||||
|
||||
Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep);
|
||||
Bool XVncExtSetParam(Display* dpy, const char* param);
|
||||
Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len);
|
||||
char* XVncExtGetParamDesc(Display* dpy, const char* param);
|
||||
char** XVncExtListParams(Display* dpy, int* nParams);
|
||||
void XVncExtFreeParamList(char** list);
|
||||
Bool XVncExtSelectInput(Display* dpy, Window w, int mask);
|
||||
Bool XVncExtConnect(Display* dpy, const char* hostAndPort);
|
||||
Bool XVncExtGetQueryConnect(Display* dpy, char** addr,
|
||||
char** user, int* timeout, void** opaqueId);
|
||||
Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve);
|
||||
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
unsigned long serial;
|
||||
Bool send_event;
|
||||
Display *display;
|
||||
Window window;
|
||||
} XVncExtQueryConnectEvent;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _VNCEXT_PROTO_
|
||||
|
||||
#define VNCEXTNAME "VNC-EXTENSION"
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtSetParam */
|
||||
CARD16 length B16;
|
||||
CARD8 paramLen;
|
||||
CARD8 pad0;
|
||||
CARD16 pad1 B16;
|
||||
} xVncExtSetParamReq;
|
||||
#define sz_xVncExtSetParamReq 8
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE success;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 pad0 B32;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtSetParamReply;
|
||||
#define sz_xVncExtSetParamReply 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtGetParam */
|
||||
CARD16 length B16;
|
||||
CARD8 paramLen;
|
||||
CARD8 pad0;
|
||||
CARD16 pad1 B16;
|
||||
} xVncExtGetParamReq;
|
||||
#define sz_xVncExtGetParamReq 8
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE success;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD16 valueLen B16;
|
||||
CARD16 pad0 B16;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtGetParamReply;
|
||||
#define sz_xVncExtGetParamReply 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtGetParamDesc */
|
||||
CARD16 length B16;
|
||||
CARD8 paramLen;
|
||||
CARD8 pad0;
|
||||
CARD16 pad1 B16;
|
||||
} xVncExtGetParamDescReq;
|
||||
#define sz_xVncExtGetParamDescReq 8
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE success;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD16 descLen B16;
|
||||
CARD16 pad0 B16;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtGetParamDescReply;
|
||||
#define sz_xVncExtGetParamDescReply 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtListParams */
|
||||
CARD16 length B16;
|
||||
} xVncExtListParamsReq;
|
||||
#define sz_xVncExtListParamsReq 4
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE pad0;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD16 nParams B16;
|
||||
CARD16 pad1 B16;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
CARD32 pad6 B32;
|
||||
} xVncExtListParamsReply;
|
||||
#define sz_xVncExtListParamsReply 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtSelectInput */
|
||||
CARD16 length B16;
|
||||
CARD32 window B32;
|
||||
CARD32 mask B32;
|
||||
} xVncExtSelectInputReq;
|
||||
#define sz_xVncExtSelectInputReq 12
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtConnect */
|
||||
CARD16 length B16;
|
||||
CARD8 strLen;
|
||||
CARD8 pad0;
|
||||
CARD16 pad1 B16;
|
||||
} xVncExtConnectReq;
|
||||
#define sz_xVncExtConnectReq 8
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE success;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 pad0 B32;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtConnectReply;
|
||||
#define sz_xVncExtConnectReply 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtGetQueryConnect */
|
||||
CARD16 length B16;
|
||||
} xVncExtGetQueryConnectReq;
|
||||
#define sz_xVncExtGetQueryConnectReq 4
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* X_Reply */
|
||||
BYTE pad0;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 length B32;
|
||||
CARD32 addrLen B32;
|
||||
CARD32 userLen B32;
|
||||
CARD32 timeout B32;
|
||||
CARD32 opaqueId B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtGetQueryConnectReply;
|
||||
#define sz_xVncExtGetQueryConnectReply 32
|
||||
|
||||
typedef struct {
|
||||
CARD8 reqType; /* always VncExtReqCode */
|
||||
CARD8 vncExtReqType; /* always VncExtApproveConnect */
|
||||
CARD16 length B16;
|
||||
CARD8 approve;
|
||||
CARD8 pad0;
|
||||
CARD16 pad1;
|
||||
CARD32 opaqueId B32;
|
||||
} xVncExtApproveConnectReq;
|
||||
#define sz_xVncExtApproveConnectReq 12
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
BYTE type; /* always eventBase + VncExtQueryConnectNotify */
|
||||
BYTE pad0;
|
||||
CARD16 sequenceNumber B16;
|
||||
CARD32 window B32;
|
||||
CARD32 pad6 B32;
|
||||
CARD32 pad1 B32;
|
||||
CARD32 pad2 B32;
|
||||
CARD32 pad3 B32;
|
||||
CARD32 pad4 B32;
|
||||
CARD32 pad5 B32;
|
||||
} xVncExtQueryConnectNotifyEvent;
|
||||
#define sz_xVncExtQueryConnectNotifyEvent 32
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
335
unix/vncconfig/vncconfig.cxx
Normal file
335
unix/vncconfig/vncconfig.cxx
Normal file
@@ -0,0 +1,335 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2012-2016 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// VNC server configuration utility
|
||||
//
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <signal.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include "vncExt.h"
|
||||
#include <rdr/Exception.h>
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/Logger_stdio.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include "TXWindow.h"
|
||||
#include "TXCheckbox.h"
|
||||
#include "TXLabel.h"
|
||||
#include "QueryConnectDialog.h"
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
LogWriter vlog("vncconfig");
|
||||
|
||||
StringParameter displayname("display", "The X display", "");
|
||||
BoolParameter noWindow("nowin", "Don't display a window", 0);
|
||||
BoolParameter iconic("iconic", "Start with window iconified", 0);
|
||||
|
||||
#define ACCEPT_CUT_TEXT "AcceptCutText"
|
||||
#define SEND_CUT_TEXT "SendCutText"
|
||||
|
||||
#define SET_PRIMARY "SetPrimary"
|
||||
#define SEND_PRIMARY "SendPrimary"
|
||||
|
||||
char* programName = 0;
|
||||
Display* dpy;
|
||||
int vncExtEventBase, vncExtErrorBase;
|
||||
|
||||
static bool getBoolParam(Display* dpy, const char* param) {
|
||||
char* data;
|
||||
int len;
|
||||
if (XVncExtGetParam(dpy, param, &data, &len)) {
|
||||
if (strcmp(data,"1") == 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class VncConfigWindow : public TXWindow, public TXEventHandler,
|
||||
public TXDeleteWindowCallback,
|
||||
public TXCheckboxCallback,
|
||||
public QueryResultCallback {
|
||||
public:
|
||||
VncConfigWindow(Display* dpy)
|
||||
: TXWindow(dpy, 300, 100),
|
||||
acceptClipboard(dpy, "Accept clipboard from viewers", this, false, this),
|
||||
setPrimaryCB(dpy, "Also set primary selection", this, false, this),
|
||||
sendClipboard(dpy, "Send clipboard to viewers", this, false, this),
|
||||
sendPrimaryCB(dpy, "Send primary selection to viewers", this,false,this),
|
||||
queryConnectDialog(0)
|
||||
{
|
||||
int y = yPad;
|
||||
acceptClipboard.move(xPad, y);
|
||||
acceptClipboard.checked(getBoolParam(dpy, ACCEPT_CUT_TEXT));
|
||||
y += acceptClipboard.height();
|
||||
setPrimaryCB.move(xPad + 10, y);
|
||||
setPrimaryCB.checked(getBoolParam(dpy, SET_PRIMARY));
|
||||
setPrimaryCB.disabled(!acceptClipboard.checked());
|
||||
y += setPrimaryCB.height();
|
||||
sendClipboard.move(xPad, y);
|
||||
sendClipboard.checked(getBoolParam(dpy, SEND_CUT_TEXT));
|
||||
y += sendClipboard.height();
|
||||
sendPrimaryCB.move(xPad + 10, y);
|
||||
sendPrimaryCB.checked(getBoolParam(dpy, SEND_PRIMARY));
|
||||
sendPrimaryCB.disabled(!sendClipboard.checked());
|
||||
y += sendPrimaryCB.height();
|
||||
setEventHandler(this);
|
||||
toplevel("VNC config", this, 0, 0, 0, iconic);
|
||||
XVncExtSelectInput(dpy, win(), VncExtQueryConnectMask);
|
||||
}
|
||||
|
||||
// handleEvent()
|
||||
|
||||
virtual void handleEvent(TXWindow* w, XEvent* ev) {
|
||||
if (ev->type == vncExtEventBase + VncExtQueryConnectNotify) {
|
||||
vlog.debug("query connection event");
|
||||
if (queryConnectDialog)
|
||||
delete queryConnectDialog;
|
||||
queryConnectDialog = 0;
|
||||
char* qcAddress;
|
||||
char* qcUser;
|
||||
int qcTimeout;
|
||||
if (XVncExtGetQueryConnect(dpy, &qcAddress, &qcUser,
|
||||
&qcTimeout, &queryConnectId)) {
|
||||
if (qcTimeout)
|
||||
queryConnectDialog = new QueryConnectDialog(dpy, qcAddress,
|
||||
qcUser, qcTimeout,
|
||||
this);
|
||||
if (queryConnectDialog)
|
||||
queryConnectDialog->map();
|
||||
XFree(qcAddress);
|
||||
XFree(qcUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TXDeleteWindowCallback method
|
||||
virtual void deleteWindow(TXWindow* w) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// TXCheckboxCallback method
|
||||
virtual void checkboxSelect(TXCheckbox* checkbox) {
|
||||
if (checkbox == &acceptClipboard) {
|
||||
XVncExtSetParam(dpy, (acceptClipboard.checked()
|
||||
? ACCEPT_CUT_TEXT "=1" : ACCEPT_CUT_TEXT "=0"));
|
||||
setPrimaryCB.disabled(!acceptClipboard.checked());
|
||||
} else if (checkbox == &sendClipboard) {
|
||||
XVncExtSetParam(dpy, (sendClipboard.checked()
|
||||
? SEND_CUT_TEXT "=1" : SEND_CUT_TEXT "=0"));
|
||||
sendPrimaryCB.disabled(!sendClipboard.checked());
|
||||
} else if (checkbox == &setPrimaryCB) {
|
||||
XVncExtSetParam(dpy, (setPrimaryCB.checked()
|
||||
? SET_PRIMARY "=1" : SET_PRIMARY "=0"));
|
||||
} else if (checkbox == &sendPrimaryCB) {
|
||||
XVncExtSetParam(dpy, (sendPrimaryCB.checked()
|
||||
? SEND_PRIMARY "=1" : SEND_PRIMARY "=0"));
|
||||
}
|
||||
}
|
||||
|
||||
// QueryResultCallback interface
|
||||
virtual void queryApproved() {
|
||||
XVncExtApproveConnect(dpy, queryConnectId, 1);
|
||||
}
|
||||
virtual void queryRejected() {
|
||||
XVncExtApproveConnect(dpy, queryConnectId, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
TXCheckbox acceptClipboard, setPrimaryCB;
|
||||
TXCheckbox sendClipboard, sendPrimaryCB;
|
||||
|
||||
QueryConnectDialog* queryConnectDialog;
|
||||
void* queryConnectId;
|
||||
};
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: %s [parameters]\n",
|
||||
programName);
|
||||
fprintf(stderr," %s [parameters] -connect <host>[:<port>]\n",
|
||||
programName);
|
||||
fprintf(stderr," %s [parameters] -disconnect\n", programName);
|
||||
fprintf(stderr," %s [parameters] [-set] <Xvnc-param>=<value> ...\n",
|
||||
programName);
|
||||
fprintf(stderr," %s [parameters] -list\n", programName);
|
||||
fprintf(stderr," %s [parameters] -get <param>\n", programName);
|
||||
fprintf(stderr," %s [parameters] -desc <param>\n",programName);
|
||||
fprintf(stderr,"\n"
|
||||
"Parameters can be turned on with -<param> or off with -<param>=0\n"
|
||||
"Parameters which take a value can be specified as "
|
||||
"-<param> <value>\n"
|
||||
"Other valid forms are <param>=<value> -<param>=<value> "
|
||||
"--<param>=<value>\n"
|
||||
"Parameter names are case-insensitive. The parameters are:\n\n");
|
||||
Configuration::listParams(79, 14);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void removeArgs(int* argc, char** argv, int first, int n)
|
||||
{
|
||||
if (first + n > *argc) return;
|
||||
for (int i = first + n; i < *argc; i++)
|
||||
argv[i-n] = argv[i];
|
||||
*argc -= n;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
programName = argv[0];
|
||||
rfb::initStdIOLoggers();
|
||||
rfb::LogWriter::setLogParams("*:stderr:30");
|
||||
|
||||
// Process vncconfig's own parameters first, then we process the
|
||||
// other arguments when we have the X display.
|
||||
int i;
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (Configuration::setParam(argv[i]))
|
||||
continue;
|
||||
|
||||
if (argv[i][0] == '-' && i+1 < argc &&
|
||||
Configuration::setParam(&argv[i][1], argv[i+1])) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
CharArray displaynameStr(displayname.getData());
|
||||
if (!(dpy = XOpenDisplay(displaynameStr.buf))) {
|
||||
fprintf(stderr,"%s: unable to open display \"%s\"\n",
|
||||
programName, XDisplayName(displaynameStr.buf));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!XVncExtQueryExtension(dpy, &vncExtEventBase, &vncExtErrorBase)) {
|
||||
fprintf(stderr,"No VNC extension on display %s\n",
|
||||
XDisplayName(displaynameStr.buf));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (i < argc) {
|
||||
for (; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-connect") == 0) {
|
||||
i++;
|
||||
if (i >= argc) usage();
|
||||
if (!XVncExtConnect(dpy, argv[i])) {
|
||||
fprintf(stderr,"connecting to %s failed\n",argv[i]);
|
||||
}
|
||||
} else if (strcmp(argv[i], "-disconnect") == 0) {
|
||||
if (!XVncExtConnect(dpy, "")) {
|
||||
fprintf(stderr,"disconnecting all clients failed\n");
|
||||
}
|
||||
} else if (strcmp(argv[i], "-get") == 0) {
|
||||
i++;
|
||||
if (i >= argc) usage();
|
||||
char* data;
|
||||
int len;
|
||||
if (XVncExtGetParam(dpy, argv[i], &data, &len)) {
|
||||
printf("%.*s\n",len,data);
|
||||
} else {
|
||||
fprintf(stderr,"getting param %s failed\n",argv[i]);
|
||||
}
|
||||
XFree(data);
|
||||
} else if (strcmp(argv[i], "-desc") == 0) {
|
||||
i++;
|
||||
if (i >= argc) usage();
|
||||
char* desc = XVncExtGetParamDesc(dpy, argv[i]);
|
||||
if (desc) {
|
||||
printf("%s\n",desc);
|
||||
} else {
|
||||
fprintf(stderr,"getting description for param %s failed\n",argv[i]);
|
||||
}
|
||||
XFree(desc);
|
||||
} else if (strcmp(argv[i], "-list") == 0) {
|
||||
int nParams;
|
||||
char** list = XVncExtListParams(dpy, &nParams);
|
||||
for (int i = 0; i < nParams; i++) {
|
||||
printf("%s\n",list[i]);
|
||||
}
|
||||
XVncExtFreeParamList(list);
|
||||
} else if (strcmp(argv[i], "-set") == 0) {
|
||||
i++;
|
||||
if (i >= argc) usage();
|
||||
if (!XVncExtSetParam(dpy, argv[i])) {
|
||||
fprintf(stderr,"setting param %s failed\n",argv[i]);
|
||||
}
|
||||
} else if (XVncExtSetParam(dpy, argv[i])) {
|
||||
fprintf(stderr,"set parameter %s\n",argv[i]);
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
TXWindow::init(dpy,"Vncconfig");
|
||||
|
||||
VncConfigWindow w(dpy);
|
||||
if (!noWindow) w.map();
|
||||
|
||||
while (true) {
|
||||
struct timeval tv;
|
||||
struct timeval* tvp = 0;
|
||||
|
||||
// Process any incoming X events
|
||||
TXWindow::handleXEvents(dpy);
|
||||
|
||||
// Process expired timers and get the time until the next one
|
||||
int timeoutMs = Timer::checkTimeouts();
|
||||
if (timeoutMs) {
|
||||
tv.tv_sec = timeoutMs / 1000;
|
||||
tv.tv_usec = (timeoutMs % 1000) * 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
// If there are X requests pending then poll, don't wait!
|
||||
if (XPending(dpy)) {
|
||||
tv.tv_usec = tv.tv_sec = 0;
|
||||
tvp = &tv;
|
||||
}
|
||||
|
||||
// Wait for X events, VNC traffic, or the next timer expiry
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(ConnectionNumber(dpy), &rfds);
|
||||
int n = select(FD_SETSIZE, &rfds, 0, 0, tvp);
|
||||
if (n < 0) throw rdr::SystemException("select",errno);
|
||||
}
|
||||
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
} catch (rdr::Exception &e) {
|
||||
vlog.error("%s", e.str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
126
unix/vncconfig/vncconfig.man
Normal file
126
unix/vncconfig/vncconfig.man
Normal file
@@ -0,0 +1,126 @@
|
||||
.TH vncconfig 1 "" "KasmVNC" "Virtual Network Computing"
|
||||
.SH NAME
|
||||
vncconfig \- configure and control a VNC server
|
||||
.SH SYNOPSIS
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
.B \-connect
|
||||
.IR host [: port ]
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
.B \-disconnect
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
.RB [ -set ]
|
||||
.IR Xvnc-param = value " ..."
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
.B \-list
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
\fB\-get\fP \fIXvnc-param\fP
|
||||
.br
|
||||
.B vncconfig
|
||||
.RI [ parameters ]
|
||||
\fB\-desc\fP \fIXvnc-param\fP
|
||||
.SH DESCRIPTION
|
||||
.B vncconfig
|
||||
is used to configure and control a running instance of Xvnc, or any other X
|
||||
server with the VNC extension. Note that it cannot be used to control VNC
|
||||
servers prior to version 4.
|
||||
|
||||
When run with no options, it runs as a kind of "helper" application for Xvnc.
|
||||
Its main purpose when run in this mode is to query the user how new
|
||||
connections should be handled (provided this feature is enabled). The
|
||||
\fB-nowin\fP flag can be used if you always want the query support but don't
|
||||
wish to clutter the desktop with the settings window - alternatively the
|
||||
\fB-iconic\fP option can be used to make it iconified by default.
|
||||
|
||||
When run in any other mode, \fBvncconfig\fP is a one-shot program used to
|
||||
configure or control Xvnc as appropriate. It can be used to tell Xvnc to
|
||||
connect or disconnect from listening viewers, and to set and retrieve Xvnc's
|
||||
parameters.
|
||||
|
||||
Note that the DISPLAY environment variable or the \fB\-display\fP option
|
||||
must be set as appropriate to control Xvnc. If you run it on an ordinary X
|
||||
server (or on a version 3 Xvnc) you will get an error message saying that there
|
||||
is no VNC extension.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B \-connect \fIhost\fP[:\fIport\fP]
|
||||
Tells an Xvnc server to make a "reverse" connection to a listening VNC viewer
|
||||
(normally connections are made the other way round - the viewer connects to the
|
||||
server). \fIhost\fP is the host where the listening viewer is running. If it's
|
||||
not listening on the default port of 5500, you can specify \fIhost:port\fP
|
||||
instead.
|
||||
.
|
||||
.TP
|
||||
.B \-disconnect
|
||||
This causes Xvnc to disconnect from all viewers so that the VNC desktop is not
|
||||
displayed anywhere.
|
||||
.
|
||||
.TP
|
||||
[\fB-set\fP] \fIXvnc-param\fP=\fIvalue\fP
|
||||
Sets an Xvnc parameter to the given value. Note that some of Xvnc's parameters
|
||||
are read only once at startup so that changing them in this way may not have
|
||||
any effect.
|
||||
.
|
||||
.TP
|
||||
.B \-list
|
||||
Lists all the parameters supported by Xvnc.
|
||||
.
|
||||
.TP
|
||||
.B \-get \fIXvnc-param\fP
|
||||
Prints the current value of the given Xvnc parameter.
|
||||
.
|
||||
.TP
|
||||
.B \-desc \fIXvnc-param\fP
|
||||
Prints a short description of the given Xvnc parameter.
|
||||
|
||||
.SH PARAMETERS
|
||||
.B vncconfig
|
||||
also has parameters of its own which can be set on the command line. These
|
||||
should not be confused with Xvnc's parameters which are manipulated with the
|
||||
\fB-set\fP, \fB-get\fP, \fB-list\fP and \fB-desc\fP options.
|
||||
|
||||
Parameters can be turned on with -\fIparam\fP or off with -\fIparam\fP=0.
|
||||
Parameters which take a value can be specified as -\fIparam\fP \fIvalue\fP.
|
||||
Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP -\fIparam\fP=\fIvalue\fP
|
||||
--\fIparam\fP=\fIvalue\fP. Parameter names are case-insensitive.
|
||||
|
||||
.TP
|
||||
.B \-display \fIXdisplay\fP
|
||||
Specifies the Xvnc server to control.
|
||||
.
|
||||
.TP
|
||||
.B \-nowin
|
||||
When run as a "helper" app, don't put up a window.
|
||||
.
|
||||
.TP
|
||||
.B \-iconic
|
||||
When run as a "helper" app, make the window iconified at startup.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR vncpasswd (1),
|
||||
.BR vncviewer (1),
|
||||
.BR vncserver (1),
|
||||
.BR Xvnc (1)
|
||||
.br
|
||||
http://kasmweb.com
|
||||
|
||||
.SH AUTHOR
|
||||
Tristan Richardson, RealVNC Ltd. and others.
|
||||
|
||||
VNC was originally developed by the RealVNC team while at Olivetti
|
||||
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
|
||||
implemented by Constantin Kaplinsky. Many other people have since
|
||||
participated in development, testing and support. This manual is part
|
||||
of the KasmVNC software suite.
|
||||
1
unix/vncpasswd/.gitignore
vendored
Normal file
1
unix/vncpasswd/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
vncpasswd
|
||||
9
unix/vncpasswd/CMakeLists.txt
Normal file
9
unix/vncpasswd/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
include_directories(${CMAKE_SOURCE_DIR}/common)
|
||||
|
||||
add_executable(vncpasswd
|
||||
vncpasswd.cxx)
|
||||
|
||||
target_link_libraries(vncpasswd tx rfb os)
|
||||
|
||||
install(TARGETS vncpasswd DESTINATION ${BIN_DIR})
|
||||
install(FILES vncpasswd.man DESTINATION ${MAN_DIR}/man1 RENAME vncpasswd.1)
|
||||
188
unix/vncpasswd/vncpasswd.cxx
Normal file
188
unix/vncpasswd/vncpasswd.cxx
Normal file
@@ -0,0 +1,188 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright (C) 2010 Antoine Martin. All Rights Reserved.
|
||||
* Copyright (C) 2010 D. R. Commander. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <os/os.h>
|
||||
#include <rfb/Password.h>
|
||||
#include <rfb/util.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
char* prog;
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: %s [file]\n", prog);
|
||||
fprintf(stderr," %s -f\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static void enableEcho(bool enable) {
|
||||
termios attrs;
|
||||
tcgetattr(fileno(stdin), &attrs);
|
||||
if (enable)
|
||||
attrs.c_lflag |= ECHO;
|
||||
else
|
||||
attrs.c_lflag &= ~ECHO;
|
||||
attrs.c_lflag |= ECHONL;
|
||||
tcsetattr(fileno(stdin), TCSAFLUSH, &attrs);
|
||||
}
|
||||
|
||||
static char* getpassword(const char* prompt) {
|
||||
PlainPasswd buf(256);
|
||||
if (prompt) fputs(prompt, stdout);
|
||||
enableEcho(false);
|
||||
char* result = fgets(buf.buf, 256, stdin);
|
||||
enableEcho(true);
|
||||
if (result) {
|
||||
if (result[strlen(result)-1] == '\n')
|
||||
result[strlen(result)-1] = 0;
|
||||
return buf.takeBuf();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reads passwords from stdin and prints encrypted passwords to stdout.
|
||||
static int encrypt_pipe() {
|
||||
int i;
|
||||
|
||||
// We support a maximum of two passwords right now
|
||||
for (i = 0;i < 2;i++) {
|
||||
char *result = getpassword(NULL);
|
||||
if (!result)
|
||||
break;
|
||||
|
||||
ObfuscatedPasswd obfuscated(result);
|
||||
if (fwrite(obfuscated.buf, obfuscated.length, 1, stdout) != 1) {
|
||||
fprintf(stderr,"Writing to stdout failed\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Did we fail to produce even one password?
|
||||
if (i == 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ObfuscatedPasswd* readpassword() {
|
||||
while (true) {
|
||||
PlainPasswd passwd(getpassword("Password:"));
|
||||
if (!passwd.buf) {
|
||||
perror("getpassword error");
|
||||
exit(1);
|
||||
}
|
||||
if (strlen(passwd.buf) < 6) {
|
||||
if (strlen(passwd.buf) == 0) {
|
||||
fprintf(stderr,"Password not changed\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr,"Password must be at least 6 characters - try again\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
PlainPasswd passwd2(getpassword("Verify:"));
|
||||
if (!passwd2.buf) {
|
||||
perror("getpass error");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(passwd.buf, passwd2.buf) != 0) {
|
||||
fprintf(stderr,"Passwords don't match - try again\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
return new ObfuscatedPasswd(passwd);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
prog = argv[0];
|
||||
|
||||
char* fname = 0;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-q") == 0) { // allowed for backwards compatibility
|
||||
} else if (strncmp(argv[i], "-f", 2) == 0) {
|
||||
return encrypt_pipe();
|
||||
} else if (argv[i][0] == '-') {
|
||||
usage();
|
||||
} else if (!fname) {
|
||||
fname = argv[i];
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (!fname) {
|
||||
char *homeDir = NULL;
|
||||
if (getvnchomedir(&homeDir) == -1) {
|
||||
fprintf(stderr, "Can't obtain VNC home directory\n");
|
||||
exit(1);
|
||||
}
|
||||
mkdir(homeDir, 0777);
|
||||
fname = new char[strlen(homeDir) + 7];
|
||||
sprintf(fname, "%spasswd", homeDir);
|
||||
delete [] homeDir;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ObfuscatedPasswd* obfuscated = readpassword();
|
||||
ObfuscatedPasswd* obfuscatedReadOnly = 0;
|
||||
|
||||
fprintf(stderr, "Would you like to enter a view-only password (y/n)? ");
|
||||
char yesno[3];
|
||||
if (fgets(yesno, 3, stdin) != NULL && (yesno[0] == 'y' || yesno[0] == 'Y')) {
|
||||
obfuscatedReadOnly = readpassword();
|
||||
}
|
||||
|
||||
FILE* fp = fopen(fname,"w");
|
||||
if (!fp) {
|
||||
fprintf(stderr,"Couldn't open %s for writing\n",fname);
|
||||
exit(1);
|
||||
}
|
||||
chmod(fname, S_IRUSR|S_IWUSR);
|
||||
|
||||
if (fwrite(obfuscated->buf, obfuscated->length, 1, fp) != 1) {
|
||||
fprintf(stderr,"Writing to %s failed\n",fname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (obfuscatedReadOnly) {
|
||||
if (fwrite(obfuscatedReadOnly->buf, obfuscatedReadOnly->length, 1, fp) != 1) {
|
||||
fprintf(stderr,"Writing to %s failed\n",fname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
59
unix/vncpasswd/vncpasswd.man
Normal file
59
unix/vncpasswd/vncpasswd.man
Normal file
@@ -0,0 +1,59 @@
|
||||
.TH vncpasswd 1 "" "KasmVNC" "Virtual Network Computing"
|
||||
.SH NAME
|
||||
vncpasswd \- change the VNC password
|
||||
.SH SYNOPSIS
|
||||
\fBvncpasswd\fR [\fIpasswd-file\fR]
|
||||
.br
|
||||
\fBvncpasswd\fR \-f
|
||||
.SH DESCRIPTION
|
||||
.B vncpasswd
|
||||
allows you to set the password used to access VNC desktops. Its default
|
||||
behavior is to prompt for a VNC password and then store an obfuscated version
|
||||
of this password to \fIpasswd-file\fR (or to $HOME/.vnc/passwd if no password
|
||||
file is specified.) The \fBvncserver\fP script runs \fBvncpasswd\fP the first
|
||||
time you start a VNC desktop, and it invokes \fBXvnc\fP with the appropriate
|
||||
\fB\-rfbauth\fP option. \fBvncviewer\fP can also be given a password file to
|
||||
use via the \fB\-passwd\fP option.
|
||||
|
||||
The password must be at least six characters long (unless the \fB\-f\fR
|
||||
command-line option is used-- see below), and only the first eight
|
||||
characters are significant. Note that the stored password is \fBnot\fP
|
||||
encrypted securely - anyone who has access to this file can trivially find out
|
||||
the plain-text password, so \fBvncpasswd\fP always sets appropriate permissions
|
||||
(read and write only by the owner.) However, when accessing a VNC desktop, a
|
||||
challenge-response mechanism is used over the wire making it hard for anyone to
|
||||
crack the password simply by snooping on the network.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.TP
|
||||
.B \-f
|
||||
Filter mode. Read a plain-text password from stdin and write an encrypted
|
||||
version to stdout. Note that in filter mode, short or even empty passwords
|
||||
will be silently accepted.
|
||||
|
||||
A view-only password must be separated from the normal password by a newline
|
||||
character.
|
||||
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
$HOME/.vnc/passwd
|
||||
Default location of the VNC password file.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR vncviewer (1),
|
||||
.BR vncserver (1),
|
||||
.BR Xvnc (1)
|
||||
.BR vncconfig (1),
|
||||
.br
|
||||
http://kasmweb.com
|
||||
|
||||
.SH AUTHORS
|
||||
Tristan Richardson, RealVNC Ltd., Antoine Martin, D. R. Commander and others.
|
||||
|
||||
VNC was originally developed by the RealVNC team while at Olivetti
|
||||
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
|
||||
implemented by Constantin Kaplinsky. Many other people have since
|
||||
participated in development, testing and support. This manual is part
|
||||
of the KasmVNC software suite.
|
||||
906
unix/vncserver
Executable file
906
unix/vncserver
Executable file
@@ -0,0 +1,906 @@
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved.
|
||||
# Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved.
|
||||
# Copyright (C) 2002-2005 RealVNC Ltd.
|
||||
# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
||||
#
|
||||
# This is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This software is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this software; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
# USA.
|
||||
#
|
||||
|
||||
#
|
||||
# vncserver - wrapper script to start an X VNC server.
|
||||
#
|
||||
|
||||
# First make sure we're operating in a sane environment.
|
||||
$exedir = "";
|
||||
$slashndx = rindex($0, "/");
|
||||
if($slashndx>=0) {
|
||||
$exedir = substr($0, 0, $slashndx+1);
|
||||
}
|
||||
|
||||
$vncClasses = "";
|
||||
|
||||
&SanityCheck();
|
||||
|
||||
#
|
||||
# Global variables. You may want to configure some of these for
|
||||
# your site
|
||||
#
|
||||
|
||||
$geometry = "1024x768";
|
||||
#$depth = 16;
|
||||
$vncJavaFiles = (((-d "$vncClasses") && "$vncClasses") ||
|
||||
((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") ||
|
||||
((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes"));
|
||||
|
||||
$vncUserDir = "$ENV{HOME}/.vnc";
|
||||
$vncUserConfig = "$vncUserDir/config";
|
||||
|
||||
$vncSystemConfigDir = "/etc/kasmvnc";
|
||||
$vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults";
|
||||
$vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory";
|
||||
|
||||
$skipxstartup = 0;
|
||||
$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";
|
||||
|
||||
$xstartupFile = $vncUserDir . "/xstartup";
|
||||
$defaultXStartup
|
||||
= ("#!/bin/sh\n\n".
|
||||
"unset SESSION_MANAGER\n".
|
||||
"unset DBUS_SESSION_BUS_ADDRESS\n".
|
||||
"OS=`uname -s`\n".
|
||||
"if [ \$OS = 'Linux' ]; then\n".
|
||||
" case \"\$WINDOWMANAGER\" in\n".
|
||||
" \*gnome\*)\n".
|
||||
" if [ -e /etc/SuSE-release ]; then\n".
|
||||
" PATH=\$PATH:/opt/gnome/bin\n".
|
||||
" export PATH\n".
|
||||
" fi\n".
|
||||
" ;;\n".
|
||||
" esac\n".
|
||||
"fi\n".
|
||||
"if [ -x /etc/X11/xinit/xinitrc ]; then\n".
|
||||
" exec /etc/X11/xinit/xinitrc\n".
|
||||
"fi\n".
|
||||
"if [ -f /etc/X11/xinit/xinitrc ]; then\n".
|
||||
" exec sh /etc/X11/xinit/xinitrc\n".
|
||||
"fi\n".
|
||||
"[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n".
|
||||
"xsetroot -solid grey\n".
|
||||
"xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n".
|
||||
"twm &\n");
|
||||
|
||||
$defaultConfig
|
||||
= ("## Supported server options to pass to vncserver upon invocation can be listed\n".
|
||||
"## in this file. See the following manpages for more: vncserver(1) Xvnc(1).\n".
|
||||
"## Several common ones are shown below. Uncomment and modify to your liking.\n".
|
||||
"##\n".
|
||||
"# securitytypes=vncauth,tlsvnc\n".
|
||||
"# desktop=sandbox\n".
|
||||
"# geometry=2000x1200\n".
|
||||
"# localhost\n".
|
||||
"# alwaysshared\n");
|
||||
|
||||
chop($host = `uname -n`);
|
||||
|
||||
if (-d "/etc/X11/fontpath.d") {
|
||||
$fontPath = "catalogue:/etc/X11/fontpath.d";
|
||||
}
|
||||
|
||||
@fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/');
|
||||
if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');}
|
||||
if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');}
|
||||
if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');}
|
||||
push(@fontpaths, '/usr/share/fonts/default');
|
||||
|
||||
@fonttypes = ('misc',
|
||||
'75dpi',
|
||||
'100dpi',
|
||||
'Speedo',
|
||||
'Type1');
|
||||
|
||||
foreach $_fpath (@fontpaths) {
|
||||
foreach $_ftype (@fonttypes) {
|
||||
if (-f "$_fpath/$_ftype/fonts.dir") {
|
||||
if (! -l "$_fpath/$_ftype") {
|
||||
$defFontPath .= "$_fpath/$_ftype,";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($defFontPath) {
|
||||
if (substr($defFontPath, -1, 1) == ',') {
|
||||
chop $defFontPath;
|
||||
}
|
||||
}
|
||||
|
||||
if ($fontPath eq "") {
|
||||
$fontPath = $defFontPath;
|
||||
}
|
||||
|
||||
# Check command line options
|
||||
|
||||
&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
|
||||
"-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1);
|
||||
|
||||
&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});
|
||||
|
||||
&Kill() if ($opt{'-kill'});
|
||||
|
||||
&List() if ($opt{'-list'});
|
||||
|
||||
# Uncomment this line if you want default geometry, depth and pixelformat
|
||||
# to match the current X display:
|
||||
# &GetXDisplayDefaults();
|
||||
|
||||
if ($opt{'-geometry'}) {
|
||||
$geometry = $opt{'-geometry'};
|
||||
}
|
||||
if ($opt{'-depth'}) {
|
||||
$depth = $opt{'-depth'};
|
||||
$pixelformat = "";
|
||||
}
|
||||
if ($opt{'-pixelformat'}) {
|
||||
$pixelformat = $opt{'-pixelformat'};
|
||||
}
|
||||
if ($opt{'-noxstartup'}) {
|
||||
$skipxstartup = 1;
|
||||
}
|
||||
if ($opt{'-xstartup'}) {
|
||||
$xstartupFile = $opt{'-xstartup'};
|
||||
}
|
||||
if ($opt{'-fp'}) {
|
||||
$fontPath = $opt{'-fp'};
|
||||
$fpArgSpecified = 1;
|
||||
}
|
||||
|
||||
&CheckGeometryAndDepth();
|
||||
|
||||
# Create the user's vnc directory if necessary.
|
||||
if (!(-e $vncUserDir)) {
|
||||
if (!mkdir($vncUserDir,0755)) {
|
||||
die "$prog: Could not create $vncUserDir.\n";
|
||||
}
|
||||
}
|
||||
|
||||
# Find display number.
|
||||
if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
|
||||
$displayNumber = $1;
|
||||
shift(@ARGV);
|
||||
if (!&CheckDisplayNumber($displayNumber)) {
|
||||
die "A VNC server is already running as :$displayNumber\n";
|
||||
}
|
||||
} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) {
|
||||
&Usage();
|
||||
} else {
|
||||
$displayNumber = &GetDisplayNumber();
|
||||
}
|
||||
|
||||
$vncPort = 5900 + $displayNumber;
|
||||
|
||||
if ($opt{'-name'}) {
|
||||
$desktopName = $opt{'-name'};
|
||||
} else {
|
||||
$desktopName = "$host:$displayNumber ($ENV{USER})";
|
||||
}
|
||||
|
||||
my %default_opts;
|
||||
my %config;
|
||||
|
||||
# We set some reasonable defaults. Config file settings
|
||||
# override these where present.
|
||||
$default_opts{desktop} = "edString($desktopName);
|
||||
$default_opts{httpd} = $vncJavaFiles if ($vncJavaFiles);
|
||||
$default_opts{auth} = "edString($xauthorityFile);
|
||||
$default_opts{geometry} = $geometry if ($geometry);
|
||||
$default_opts{depth} = $depth if ($depth);
|
||||
$default_opts{pixelformat} = $pixelformat if ($pixelformat);
|
||||
$default_opts{rfbwait} = 30000;
|
||||
$default_opts{rfbauth} = "$vncUserDir/passwd";
|
||||
$default_opts{rfbport} = $vncPort;
|
||||
$default_opts{fp} = $fontPath if ($fontPath);
|
||||
$default_opts{pn} = "";
|
||||
|
||||
# Load user-overrideable system defaults
|
||||
LoadConfig($vncSystemConfigDefaultsFile);
|
||||
|
||||
# Then the user's settings
|
||||
LoadConfig($vncUserConfig);
|
||||
|
||||
# And then override anything set above if mandatory settings exist.
|
||||
# WARNING: "Mandatory" is used loosely here! As the man page says,
|
||||
# there is nothing stopping someone from EASILY subverting the
|
||||
# settings in $vncSystemConfigMandatoryFile by simply passing
|
||||
# CLI args to vncserver, which trump config files! To properly
|
||||
# hard force policy in a non-subvertible way would require major
|
||||
# development work that touches Xvnc itself.
|
||||
LoadConfig($vncSystemConfigMandatoryFile, 1);
|
||||
|
||||
#
|
||||
# Check whether VNC authentication is enabled, and if so, prompt the user to
|
||||
# create a VNC password if they don't already have one.
|
||||
#
|
||||
|
||||
$securityTypeArgSpecified = 0;
|
||||
$vncAuthEnabled = 0;
|
||||
$passwordArgSpecified = 0;
|
||||
@vncAuthStrings = ("vncauth", "tlsvnc", "x509vnc");
|
||||
|
||||
# ...first we check our configuration files' settings
|
||||
if ($config{'securitytypes'}) {
|
||||
$securityTypeArgSpecified = 1;
|
||||
foreach $arg2 (split(',', $config{'securitytypes'})) {
|
||||
if (grep {$_ eq lc($arg2)} @vncAuthStrings) {
|
||||
$vncAuthEnabled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ...and finally we check CLI args, which in the case of the topic at
|
||||
# hand (VNC auth or not), override anything found in configuration files
|
||||
# (even so-called "mandatory" settings).
|
||||
for ($i = 0; $i < @ARGV; ++$i) {
|
||||
# -SecurityTypes can be followed by a space or "="
|
||||
my @splitargs = split('=', $ARGV[$i]);
|
||||
if (@splitargs <= 1 && $i < @ARGV - 1) {
|
||||
push(@splitargs, $ARGV[$i + 1]);
|
||||
}
|
||||
if (lc(@splitargs[0]) eq "-securitytypes") {
|
||||
if (@splitargs > 1) {
|
||||
$securityTypeArgSpecified = 1;
|
||||
}
|
||||
foreach $arg2 (split(',', @splitargs[1])) {
|
||||
if (grep {$_ eq lc($arg2)} @vncAuthStrings) {
|
||||
$vncAuthEnabled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((lc(@splitargs[0]) eq "-password")
|
||||
|| (lc(@splitargs[0]) eq "-passwordfile"
|
||||
|| (lc(@splitargs[0]) eq "-rfbauth"))) {
|
||||
$passwordArgSpecified = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) {
|
||||
($z,$z,$mode) = stat("$vncUserDir/passwd");
|
||||
if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
|
||||
warn "\nYou will require a password to access your desktops.\n\n";
|
||||
system($exedir."vncpasswd -q $vncUserDir/passwd");
|
||||
if (($? >> 8) != 0) {
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$desktopLog = "$vncUserDir/$host:$displayNumber.log";
|
||||
unlink($desktopLog);
|
||||
|
||||
# Make an X server cookie and set up the Xauthority file
|
||||
# mcookie is a part of util-linux, usually only GNU/Linux systems have it.
|
||||
$cookie = `mcookie`;
|
||||
# Fallback for non GNU/Linux OS - use /dev/urandom on systems that have it,
|
||||
# otherwise use perl's random number generator, seeded with the sum
|
||||
# of the current time, our PID and part of the encrypted form of the password.
|
||||
if ($cookie eq "" && open(URANDOM, '<', '/dev/urandom')) {
|
||||
my $randata;
|
||||
if (sysread(URANDOM, $randata, 16) == 16) {
|
||||
$cookie = unpack 'h*', $randata;
|
||||
}
|
||||
close(URANDOM);
|
||||
}
|
||||
if ($cookie eq "") {
|
||||
srand(time+$$+unpack("L",`cat $vncUserDir/passwd`));
|
||||
for (1..16) {
|
||||
$cookie .= sprintf("%02x", int(rand(256)) % 256);
|
||||
}
|
||||
}
|
||||
|
||||
open(XAUTH, "|xauth -f $xauthorityFile source -");
|
||||
print XAUTH "add $host:$displayNumber . $cookie\n";
|
||||
print XAUTH "add $host/unix:$displayNumber . $cookie\n";
|
||||
close(XAUTH);
|
||||
|
||||
# Now start the X VNC Server
|
||||
|
||||
# We build up our Xvnc command with options
|
||||
$cmd = $exedir."Xvnc :$displayNumber";
|
||||
|
||||
foreach my $k (sort keys %config) {
|
||||
$cmd .= " -$k $config{$k}";
|
||||
delete $default_opts{$k}; # file options take precedence
|
||||
}
|
||||
|
||||
foreach my $k (sort keys %default_opts) {
|
||||
$cmd .= " -$k $default_opts{$k}";
|
||||
}
|
||||
|
||||
# Add color database stuff here, e.g.:
|
||||
# $cmd .= " -co /usr/lib/X11/rgb";
|
||||
|
||||
foreach $arg (@ARGV) {
|
||||
$cmd .= " " . "edString($arg);
|
||||
}
|
||||
$cmd .= " >> " . "edString($desktopLog) . " 2>&1";
|
||||
|
||||
# Run $cmd and record the process ID.
|
||||
$pidFile = "$vncUserDir/$host:$displayNumber.pid";
|
||||
system("$cmd & echo \$! >$pidFile");
|
||||
|
||||
# Give Xvnc a chance to start up
|
||||
|
||||
sleep(3);
|
||||
if ($fontPath ne $defFontPath) {
|
||||
unless (kill 0, `cat $pidFile`) {
|
||||
if ($fpArgSpecified) {
|
||||
warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n";
|
||||
warn "path you specified using the -fp argument is incorrect. Attempting to\n";
|
||||
warn "determine an appropriate font path for this system and restart Xvnc using\n";
|
||||
warn "that font path ...\n";
|
||||
} else {
|
||||
warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n";
|
||||
warn "catalog is not properly configured. Attempting to determine an appropriate\n";
|
||||
warn "font path for this system and restart Xvnc using that font path ...\n";
|
||||
}
|
||||
$cmd =~ s@-fp [^ ]+@@;
|
||||
$cmd .= " -fp $defFontPath" if ($defFontPath);
|
||||
system("$cmd & echo \$! >$pidFile");
|
||||
sleep(3);
|
||||
}
|
||||
}
|
||||
unless (kill 0, `cat $pidFile`) {
|
||||
warn "Could not start Xvnc.\n\n";
|
||||
unlink $pidFile;
|
||||
open(LOG, "<$desktopLog");
|
||||
while (<LOG>) { print; }
|
||||
close(LOG);
|
||||
die "\n";
|
||||
}
|
||||
|
||||
warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
|
||||
|
||||
# Create the user's xstartup script if necessary.
|
||||
if (! $skipxstartup) {
|
||||
if (!(-e "$xstartupFile")) {
|
||||
warn "Creating default startup script $xstartupFile\n";
|
||||
open(XSTARTUP, ">$xstartupFile");
|
||||
print XSTARTUP $defaultXStartup;
|
||||
close(XSTARTUP);
|
||||
chmod 0755, "$xstartupFile";
|
||||
}
|
||||
}
|
||||
|
||||
# Create the user's config file if necessary.
|
||||
if (!(-e "$vncUserDir/config")) {
|
||||
warn "Creating default config $vncUserDir/config\n";
|
||||
open(VNCUSERCONFIG, ">$vncUserDir/config");
|
||||
print VNCUSERCONFIG $defaultConfig;
|
||||
close(VNCUSERCONFIG);
|
||||
chmod 0644, "$vncUserDir/config";
|
||||
}
|
||||
|
||||
# Run the X startup script.
|
||||
if (! $skipxstartup) {
|
||||
warn "Starting applications specified in $xstartupFile\n";
|
||||
}
|
||||
warn "Log file is $desktopLog\n\n";
|
||||
|
||||
# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
|
||||
# TCP (DISPLAY=host:n)
|
||||
|
||||
if (-e "/tmp/.X11-unix/X$displayNumber" ||
|
||||
-e "/usr/spool/sockets/X11/$displayNumber")
|
||||
{
|
||||
$ENV{DISPLAY}= ":$displayNumber";
|
||||
} else {
|
||||
$ENV{DISPLAY}= "$host:$displayNumber";
|
||||
}
|
||||
$ENV{VNCDESKTOP}= $desktopName;
|
||||
|
||||
if ($opt{'-fg'}) {
|
||||
if (! $skipxstartup) {
|
||||
system("$xstartupFile >> " . "edString($desktopLog) . " 2>&1");
|
||||
}
|
||||
if (kill 0, `cat $pidFile`) {
|
||||
$opt{'-kill'} = ':'.$displayNumber;
|
||||
&Kill();
|
||||
}
|
||||
} else {
|
||||
if ($opt{'-autokill'}) {
|
||||
if (! $skipxstartup) {
|
||||
system("($xstartupFile; $0 -kill :$displayNumber) >> "
|
||||
. "edString($desktopLog) . " 2>&1 &");
|
||||
}
|
||||
} else {
|
||||
if (! $skipxstartup) {
|
||||
system("$xstartupFile >> " . "edString($desktopLog)
|
||||
. " 2>&1 &");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit;
|
||||
|
||||
###############################################################################
|
||||
# Functions
|
||||
###############################################################################
|
||||
|
||||
#
|
||||
# Populate the global %config hash with settings from a specified
|
||||
# vncserver configuration file if it exists
|
||||
#
|
||||
# Args: 1. file path
|
||||
# 2. optional boolean flag to enable warning when a previously
|
||||
# set configuration setting is being overridden
|
||||
#
|
||||
sub LoadConfig {
|
||||
local ($configFile, $warnoverride) = @_;
|
||||
local ($toggle) = undef;
|
||||
|
||||
if (stat($configFile)) {
|
||||
if (open(IN, $configFile)) {
|
||||
while (<IN>) {
|
||||
next if /^#/;
|
||||
if (my ($k, $v) = /^\s*(\w+)\s*=\s*(.+)$/) {
|
||||
$k = lc($k); # must normalize key case
|
||||
if ($warnoverride && $config{$k}) {
|
||||
print("Warning: $configFile is overriding previously defined '$k' to be '$v'\n");
|
||||
}
|
||||
$config{$k} = $v;
|
||||
} elsif ($_ =~ m/^\s*(\S+)/) {
|
||||
# We can't reasonably warn on override of toggles (e.g. AlwaysShared)
|
||||
# because it would get crazy to do so. We'd have to check if the
|
||||
# current config file being loaded defined the logical opposite setting
|
||||
# (NeverShared vs. AlwaysShared, etc etc).
|
||||
$toggle = lc($1); # must normalize key case
|
||||
$config{$toggle} = $k;
|
||||
}
|
||||
}
|
||||
close(IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# CheckGeometryAndDepth simply makes sure that the geometry and depth values
|
||||
# are sensible.
|
||||
#
|
||||
|
||||
sub CheckGeometryAndDepth
|
||||
{
|
||||
if ($geometry =~ /^(\d+)x(\d+)$/) {
|
||||
$width = $1; $height = $2;
|
||||
|
||||
if (($width<1) || ($height<1)) {
|
||||
die "$prog: geometry $geometry is invalid\n";
|
||||
}
|
||||
|
||||
$geometry = "${width}x$height";
|
||||
} else {
|
||||
die "$prog: geometry $geometry is invalid\n";
|
||||
}
|
||||
|
||||
if ($depth && (($depth < 8) || ($depth > 32))) {
|
||||
die "Depth must be between 8 and 32\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# GetDisplayNumber gets the lowest available display number. A display number
|
||||
# n is taken if something is listening on the VNC server port (5900+n) or the
|
||||
# X server port (6000+n).
|
||||
#
|
||||
|
||||
sub GetDisplayNumber
|
||||
{
|
||||
foreach $n (1..99) {
|
||||
if (&CheckDisplayNumber($n)) {
|
||||
return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
|
||||
}
|
||||
}
|
||||
|
||||
die "$prog: no free display number on $host.\n";
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# CheckDisplayNumber checks if the given display number is available. A
|
||||
# display number n is taken if something is listening on the VNC server port
|
||||
# (5900+n) or the X server port (6000+n).
|
||||
#
|
||||
|
||||
sub CheckDisplayNumber
|
||||
{
|
||||
local ($n) = @_;
|
||||
|
||||
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
|
||||
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
|
||||
if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
|
||||
close(S);
|
||||
return 0;
|
||||
}
|
||||
close(S);
|
||||
|
||||
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
|
||||
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
|
||||
if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
|
||||
close(S);
|
||||
return 0;
|
||||
}
|
||||
close(S);
|
||||
|
||||
if (-e "/tmp/.X$n-lock") {
|
||||
warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
|
||||
warn "Remove this file if there is no X server $host:$n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (-e "/tmp/.X11-unix/X$n") {
|
||||
warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
|
||||
warn "Remove this file if there is no X server $host:$n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (-e "/usr/spool/sockets/X11/$n") {
|
||||
warn("\nWarning: $host:$n is taken because of ".
|
||||
"/usr/spool/sockets/X11/$n\n");
|
||||
warn "Remove this file if there is no X server $host:$n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
|
||||
# format of the current X display being used. If successful, it sets the
|
||||
# options as appropriate so that the X VNC server will use the same settings
|
||||
# (minus an allowance for window manager decorations on the geometry). Using
|
||||
# the same depth and pixel format means that the VNC server won't have to
|
||||
# translate pixels when the desktop is being viewed on this X display (for
|
||||
# TrueColor displays anyway).
|
||||
#
|
||||
|
||||
sub GetXDisplayDefaults
|
||||
{
|
||||
local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
|
||||
$red, $green, $blue);
|
||||
|
||||
$wmDecorationWidth = 4; # a guess at typical size for window manager
|
||||
$wmDecorationHeight = 24; # decoration size
|
||||
|
||||
return if (!defined($ENV{DISPLAY}));
|
||||
|
||||
@lines = `xdpyinfo 2>/dev/null`;
|
||||
|
||||
return if ($? != 0);
|
||||
|
||||
@matchlines = grep(/dimensions/, @lines);
|
||||
if (@matchlines) {
|
||||
($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);
|
||||
|
||||
$width -= $wmDecorationWidth;
|
||||
$height -= $wmDecorationHeight;
|
||||
|
||||
$geometry = "${width}x$height";
|
||||
}
|
||||
|
||||
@matchlines = grep(/default visual id/, @lines);
|
||||
if (@matchlines) {
|
||||
($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);
|
||||
|
||||
for ($i = 0; $i < @lines; $i++) {
|
||||
if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
|
||||
if (($lines[$i+1] !~ /TrueColor/) ||
|
||||
($lines[$i+2] !~ /depth/) ||
|
||||
($lines[$i+4] !~ /red, green, blue masks/))
|
||||
{
|
||||
return;
|
||||
}
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return if ($i >= @lines);
|
||||
|
||||
($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
|
||||
($red,$green,$blue)
|
||||
= ($lines[$i+4]
|
||||
=~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);
|
||||
|
||||
$red = hex($red);
|
||||
$green = hex($green);
|
||||
$blue = hex($blue);
|
||||
|
||||
if ($red > $blue) {
|
||||
$red = int(log($red) / log(2)) - int(log($green) / log(2));
|
||||
$green = int(log($green) / log(2)) - int(log($blue) / log(2));
|
||||
$blue = int(log($blue) / log(2)) + 1;
|
||||
$pixelformat = "rgb$red$green$blue";
|
||||
} else {
|
||||
$blue = int(log($blue) / log(2)) - int(log($green) / log(2));
|
||||
$green = int(log($green) / log(2)) - int(log($red) / log(2));
|
||||
$red = int(log($red) / log(2)) + 1;
|
||||
$pixelformat = "bgr$blue$green$red";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# quotedString returns a string which yields the original string when parsed
|
||||
# by a shell.
|
||||
#
|
||||
|
||||
sub quotedString
|
||||
{
|
||||
local ($in) = @_;
|
||||
|
||||
$in =~ s/\'/\'\"\'\"\'/g;
|
||||
|
||||
return "'$in'";
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# removeSlashes turns slashes into underscores for use as a file name.
|
||||
#
|
||||
|
||||
sub removeSlashes
|
||||
{
|
||||
local ($in) = @_;
|
||||
|
||||
$in =~ s|/|_|g;
|
||||
|
||||
return "$in";
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Usage
|
||||
#
|
||||
|
||||
sub Usage
|
||||
{
|
||||
die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n".
|
||||
" [-geometry <width>x<height>]\n".
|
||||
" [-pixelformat rgbNNN|bgrNNN]\n".
|
||||
" [-fp <font-path>]\n".
|
||||
" [-fg]\n".
|
||||
" [-autokill]\n".
|
||||
" [-noxstartup]\n".
|
||||
" [-xstartup <file>]\n".
|
||||
" <Xvnc-options>...\n\n".
|
||||
" $prog -kill <X-display>\n\n".
|
||||
" $prog -list\n\n");
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# List
|
||||
#
|
||||
|
||||
sub List
|
||||
{
|
||||
opendir(dir, $vncUserDir);
|
||||
my @filelist = readdir(dir);
|
||||
closedir(dir);
|
||||
print "\nKasmVNC server sessions:\n\n";
|
||||
print "X DISPLAY #\tPROCESS ID\n";
|
||||
foreach my $file (@filelist) {
|
||||
if ($file =~ /$host:(\d+)$\.pid/) {
|
||||
chop($tmp_pid = `cat $vncUserDir/$file`);
|
||||
if (kill 0, $tmp_pid) {
|
||||
print ":".$1."\t\t".`cat $vncUserDir/$file`;
|
||||
} else {
|
||||
unlink ($vncUserDir . "/" . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Kill
|
||||
#
|
||||
|
||||
sub Kill
|
||||
{
|
||||
$opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1
|
||||
|
||||
if ($opt{'-kill'} =~ /^:\d+$/) {
|
||||
$pidFile = "$vncUserDir/$host$opt{'-kill'}.pid";
|
||||
} else {
|
||||
if ($opt{'-kill'} !~ /^$host:/) {
|
||||
die "\nCan't tell if $opt{'-kill'} is on $host\n".
|
||||
"Use -kill :<number> instead\n\n";
|
||||
}
|
||||
$pidFile = "$vncUserDir/$opt{'-kill'}.pid";
|
||||
}
|
||||
|
||||
if (! -r $pidFile) {
|
||||
die "\nCan't find file $pidFile\n".
|
||||
"You'll have to kill the Xvnc process manually\n\n";
|
||||
}
|
||||
|
||||
$SIG{'HUP'} = 'IGNORE';
|
||||
chop($pid = `cat $pidFile`);
|
||||
warn "Killing Xvnc process ID $pid\n";
|
||||
|
||||
if (kill 0, $pid) {
|
||||
system("kill $pid");
|
||||
sleep(1);
|
||||
if (kill 0, $pid) {
|
||||
print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n";
|
||||
print " ".$0." -kill ".$opt{'-kill'}."\n";
|
||||
print "to clean up the socket files.\n";
|
||||
exit
|
||||
}
|
||||
|
||||
} else {
|
||||
warn "Xvnc process ID $pid already killed\n";
|
||||
$opt{'-kill'} =~ s/://;
|
||||
|
||||
if (-e "/tmp/.X11-unix/X$opt{'-kill'}") {
|
||||
print "Xvnc did not appear to shut down cleanly.";
|
||||
print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n";
|
||||
unlink "/tmp/.X11-unix/X$opt{'-kill'}";
|
||||
}
|
||||
if (-e "/tmp/.X$opt{'-kill'}-lock") {
|
||||
print "Xvnc did not appear to shut down cleanly.";
|
||||
print " Removing /tmp/.X$opt{'-kill'}-lock\n";
|
||||
unlink "/tmp/.X$opt{'-kill'}-lock";
|
||||
}
|
||||
}
|
||||
|
||||
unlink $pidFile;
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# ParseOptions takes a list of possible options and a boolean indicating
|
||||
# whether the option has a value following, and sets up an associative array
|
||||
# %opt of the values of the options given on the command line. It removes all
|
||||
# the arguments it uses from @ARGV and returns them in @optArgs.
|
||||
#
|
||||
|
||||
sub ParseOptions
|
||||
{
|
||||
local (@optval) = @_;
|
||||
local ($opt, @opts, %valFollows, @newargs);
|
||||
|
||||
while (@optval) {
|
||||
$opt = shift(@optval);
|
||||
push(@opts,$opt);
|
||||
$valFollows{$opt} = shift(@optval);
|
||||
}
|
||||
|
||||
@optArgs = ();
|
||||
%opt = ();
|
||||
|
||||
arg: while (defined($arg = shift(@ARGV))) {
|
||||
foreach $opt (@opts) {
|
||||
if ($arg eq $opt) {
|
||||
push(@optArgs, $arg);
|
||||
if ($valFollows{$opt}) {
|
||||
if (@ARGV == 0) {
|
||||
&Usage();
|
||||
}
|
||||
$opt{$opt} = shift(@ARGV);
|
||||
push(@optArgs, $opt{$opt});
|
||||
} else {
|
||||
$opt{$opt} = 1;
|
||||
}
|
||||
next arg;
|
||||
}
|
||||
}
|
||||
push(@newargs,$arg);
|
||||
}
|
||||
|
||||
@ARGV = @newargs;
|
||||
}
|
||||
|
||||
|
||||
# Routine to make sure we're operating in a sane environment.
|
||||
sub SanityCheck
|
||||
{
|
||||
local ($cmd);
|
||||
|
||||
# Get the program name
|
||||
($prog) = ($0 =~ m|([^/]+)$|);
|
||||
|
||||
#
|
||||
# Check we have all the commands we'll need on the path.
|
||||
#
|
||||
|
||||
cmd:
|
||||
foreach $cmd ("uname","xauth") {
|
||||
for (split(/:/,$ENV{PATH})) {
|
||||
if (-x "$_/$cmd") {
|
||||
next cmd;
|
||||
}
|
||||
}
|
||||
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
|
||||
}
|
||||
|
||||
if($exedir eq "") {
|
||||
cmd2:
|
||||
foreach $cmd ("Xvnc","vncpasswd") {
|
||||
for (split(/:/,$ENV{PATH})) {
|
||||
if (-x "$_/$cmd") {
|
||||
$vncClasses = "$_/../vnc/classes";
|
||||
next cmd2;
|
||||
}
|
||||
}
|
||||
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
cmd3:
|
||||
foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") {
|
||||
for (split(/:/,$ENV{PATH})) {
|
||||
if (-x "$cmd") {
|
||||
$vncClasses = $exedir."../vnc/classes";
|
||||
next cmd3;
|
||||
}
|
||||
}
|
||||
die "$prog: couldn't find \"$cmd\".\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined($ENV{HOME})) {
|
||||
die "$prog: The HOME environment variable is not set.\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
|
||||
# eval, and if it fails we try 'require "sys/socket.ph"'. If this fails,
|
||||
# we just guess at the values. If you find perl moaning here, just
|
||||
# hard-code the values of AF_INET and SOCK_STREAM. You can find these out
|
||||
# for your platform by looking in /usr/include/sys/socket.h and related
|
||||
# files.
|
||||
#
|
||||
|
||||
chop($os = `uname`);
|
||||
chop($osrev = `uname -r`);
|
||||
|
||||
eval 'use Socket';
|
||||
if ($@) {
|
||||
eval 'require "sys/socket.ph"';
|
||||
if ($@) {
|
||||
if (($os eq "SunOS") && ($osrev !~ /^4/)) {
|
||||
$AF_INET = 2;
|
||||
$SOCK_STREAM = 2;
|
||||
} else {
|
||||
$AF_INET = 2;
|
||||
$SOCK_STREAM = 1;
|
||||
}
|
||||
} else {
|
||||
$AF_INET = &AF_INET;
|
||||
$SOCK_STREAM = &SOCK_STREAM;
|
||||
}
|
||||
} else {
|
||||
$AF_INET = &AF_INET;
|
||||
$SOCK_STREAM = &SOCK_STREAM;
|
||||
}
|
||||
}
|
||||
204
unix/vncserver.man
Normal file
204
unix/vncserver.man
Normal file
@@ -0,0 +1,204 @@
|
||||
.TH vncserver 1 "" "KasmVNC" "Virtual Network Computing"
|
||||
.SH NAME
|
||||
vncserver \- start or stop a VNC server
|
||||
.SH SYNOPSIS
|
||||
.B vncserver
|
||||
.RI [: display# ]
|
||||
.RB [ \-name
|
||||
.IR desktop-name ]
|
||||
.RB [ \-geometry
|
||||
.IR width x height ]
|
||||
.RB [ \-depth
|
||||
.IR depth ]
|
||||
.RB [ \-pixelformat
|
||||
.IR format ]
|
||||
.RB [ \-fp
|
||||
.IR font-path ]
|
||||
.RB [ \-fg ]
|
||||
.RB [ \-autokill ]
|
||||
.RB [ \-noxstartup ]
|
||||
.RB [ \-xstartup
|
||||
.IR script ]
|
||||
.RI [ Xvnc-options... ]
|
||||
.br
|
||||
.BI "vncserver \-kill :" display#
|
||||
.br
|
||||
.BI "vncserver \-list"
|
||||
.SH DESCRIPTION
|
||||
.B vncserver
|
||||
is used to start a VNC (Virtual Network Computing) desktop.
|
||||
.B vncserver
|
||||
is a Perl script which simplifies the process of starting an Xvnc server. It
|
||||
runs Xvnc with appropriate options and starts a window manager on the VNC
|
||||
desktop.
|
||||
|
||||
.B vncserver
|
||||
can be run with no options at all. In this case it will choose the first
|
||||
available display number (usually :1), start Xvnc with that display number,
|
||||
and start the default window manager in the Xvnc session. You can also
|
||||
specify the display number, in which case vncserver will attempt to start
|
||||
Xvnc with that display number and exit if the display number is not
|
||||
available. For example:
|
||||
|
||||
.RS
|
||||
vncserver :13
|
||||
.RE
|
||||
|
||||
Editing the file $HOME/.vnc/xstartup allows you to change the applications run
|
||||
at startup (but note that this will not affect an existing VNC session.)
|
||||
|
||||
.SH OPTIONS
|
||||
You can get a list of options by passing \fB\-h\fP as an option to vncserver.
|
||||
In addition to the options listed below, any unrecognised options will be
|
||||
passed to Xvnc - see the Xvnc man page, or "Xvnc \-help", for details.
|
||||
|
||||
.TP
|
||||
.B \-name \fIdesktop-name\fP
|
||||
Each VNC desktop has a name which may be displayed by the viewer. The desktop
|
||||
name defaults to "\fIhost\fP:\fIdisplay#\fP (\fIusername\fP)", but you can
|
||||
change it with this option. The desktop name option is passed to the xstartup
|
||||
script via the $VNCDESKTOP environment variable, which allows you to run a
|
||||
different set of applications depending on the name of the desktop.
|
||||
.
|
||||
.TP
|
||||
.B \-geometry \fIwidth\fPx\fIheight\fP
|
||||
Specify the size of the VNC desktop to be created. Default is 1024x768.
|
||||
.
|
||||
.TP
|
||||
.B \-depth \fIdepth\fP
|
||||
Specify the pixel depth (in bits) of the VNC desktop to be created. Default is
|
||||
24. Other possible values are 8, 15 and 16 - anything else is likely to cause
|
||||
strange behaviour by applications.
|
||||
.
|
||||
.TP
|
||||
.B \-pixelformat \fIformat\fP
|
||||
Specify pixel format for Xvnc to use (BGRnnn or RGBnnn). The default for
|
||||
depth 8 is BGR233 (meaning the most significant two bits represent blue, the
|
||||
next three green, and the least significant three represent red), the default
|
||||
for depth 16 is RGB565, and the default for depth 24 is RGB888.
|
||||
.
|
||||
.TP
|
||||
.B \-cc 3
|
||||
As an alternative to the default TrueColor visual, this allows you to run an
|
||||
Xvnc server with a PseudoColor visual (i.e. one which uses a color map or
|
||||
palette), which can be useful for running some old X applications which only
|
||||
work on such a display. Values other than 3 (PseudoColor) and 4 (TrueColor)
|
||||
for the \-cc option may result in strange behaviour, and PseudoColor desktops
|
||||
must have an 8-bit depth.
|
||||
.
|
||||
.TP
|
||||
.B \-kill :\fIdisplay#\fP
|
||||
This kills a VNC desktop previously started with vncserver. It does this by
|
||||
killing the Xvnc process, whose process ID is stored in the file
|
||||
"$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid". The
|
||||
.B \-kill
|
||||
option ignores anything preceding the first colon (":") in the display
|
||||
argument. Thus, you can invoke "vncserver \-kill $DISPLAY", for example at the
|
||||
end of your xstartup file after a particular application exits.
|
||||
.
|
||||
.TP
|
||||
.B \-fp \fIfont-path\fP
|
||||
If the vncserver script detects that the X Font Server (XFS) is running, it
|
||||
will attempt to start Xvnc and configure Xvnc to use XFS for font handling.
|
||||
Otherwise, if XFS is not running, the vncserver script will attempt to start
|
||||
Xvnc and allow Xvnc to use its own preferred method of font handling (which may
|
||||
be a hard-coded font path or, on more recent systems, a font catalog.) In
|
||||
any case, if Xvnc fails to start, the vncserver script will then attempt to
|
||||
determine an appropriate X font path for this system and start Xvnc using
|
||||
that font path.
|
||||
|
||||
The
|
||||
.B \-fp
|
||||
argument allows you to override the above fallback logic and specify a font
|
||||
path for Xvnc to use.
|
||||
.
|
||||
.TP
|
||||
.B \-fg
|
||||
Runs Xvnc as a foreground process. This has two effects: (1) The VNC server
|
||||
can be aborted with CTRL-C, and (2) the VNC server will exit as soon as the
|
||||
user logs out of the window manager in the VNC session. This may be necessary
|
||||
when launching KasmVNC from within certain grid computing environments.
|
||||
.
|
||||
.TP
|
||||
.B \-autokill
|
||||
Automatically kill Xvnc whenever the xstartup script exits. In most cases,
|
||||
this has the effect of terminating Xvnc when the user logs out of the window
|
||||
manager.
|
||||
.
|
||||
.TP
|
||||
.B \-noxstartup
|
||||
Do not run the %HOME/.vnc/xstartup script after launching Xvnc. This
|
||||
option allows you to manually start a window manager in your KasmVNC session.
|
||||
.
|
||||
.TP
|
||||
.B \-xstartup \fIscript\fP
|
||||
Run a custom startup script, instead of %HOME/.vnc/xstartup, after launching
|
||||
Xvnc. This is useful to run full-screen applications.
|
||||
.
|
||||
.TP
|
||||
.B \-list
|
||||
Lists all VNC desktops started by vncserver.
|
||||
|
||||
.SH FILES
|
||||
Several VNC-related files are found in the directory $HOME/.vnc:
|
||||
.TP
|
||||
$HOME/.vnc/xstartup
|
||||
A shell script specifying X applications to be run when a VNC desktop is
|
||||
started. If this file does not exist, then vncserver will create a default
|
||||
xstartup script which attempts to launch your chosen window manager.
|
||||
.TP
|
||||
/etc/kasmvnc/vncserver-config-defaults
|
||||
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
|
||||
and defines options to be passed to Xvnc, they will be used as defaults for
|
||||
users. The user's $HOME/.vnc/config overrides settings configured in this file.
|
||||
The overall configuration file load order is: this file, $HOME/.vnc/config,
|
||||
and then /etc/kasmvnc/vncserver-config-mandatory. None are required to exist.
|
||||
.TP
|
||||
/etc/kasmvnc/vncserver-config-mandatory
|
||||
The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
|
||||
and defines options to be passed to Xvnc, they will override any of the same
|
||||
options defined in a user's $HOME/.vnc/config. This file offers a mechanism
|
||||
to establish some basic form of system-wide policy. WARNING! There is
|
||||
nothing stopping users from constructing their own vncserver-like script
|
||||
that calls Xvnc directly to bypass any options defined in
|
||||
/etc/kasmvnc/vncserver-config-mandatory. Likewise, any CLI arguments passed
|
||||
to vncserver will override ANY config file setting of the same name. The
|
||||
overall configuration file load order is:
|
||||
/etc/kasmvnc/vncserver-config-defaults, $HOME/.vnc/config, and then this file.
|
||||
None are required to exist.
|
||||
.TP
|
||||
$HOME/.vnc/config
|
||||
An optional server config file wherein options to be passed to Xvnc are listed
|
||||
to avoid hard-coding them to the physical invocation. List options in this file
|
||||
one per line. For those requiring an argument, simply separate the option from
|
||||
the argument with an equal sign, for example: "geometry=2000x1200" or
|
||||
"securitytypes=vncauth,tlsvnc". Options without an argument are simply listed
|
||||
as a single word, for example: "localhost" or "alwaysshared".
|
||||
.TP
|
||||
$HOME/.vnc/passwd
|
||||
The VNC password file.
|
||||
.TP
|
||||
$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
|
||||
The log file for Xvnc and applications started in xstartup.
|
||||
.TP
|
||||
$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid
|
||||
Identifies the Xvnc process ID, used by the
|
||||
.B \-kill
|
||||
option.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR vncviewer (1),
|
||||
.BR vncpasswd (1),
|
||||
.BR vncconfig (1),
|
||||
.BR Xvnc (1)
|
||||
.br
|
||||
http://kasmweb.com
|
||||
|
||||
.SH AUTHOR
|
||||
Tristan Richardson, RealVNC Ltd., D. R. Commander and others.
|
||||
|
||||
VNC was originally developed by the RealVNC team while at Olivetti
|
||||
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
|
||||
implemented by Constantin Kaplinsky. Many other people have since
|
||||
participated in development, testing and support. This manual is part
|
||||
of the KasmVNC software suite.
|
||||
1
unix/xserver/hw/vnc/.gitignore
vendored
Normal file
1
unix/xserver/hw/vnc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
Xvnc
|
||||
689
unix/xserver/hw/vnc/Input.c
Normal file
689
unix/xserver/hw/vnc/Input.c
Normal file
@@ -0,0 +1,689 @@
|
||||
/* Copyright (C) 2009 TightVNC Team
|
||||
* Copyright (C) 2009, 2014 Red Hat, Inc.
|
||||
* Copyright 2013-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "xorg-version.h"
|
||||
|
||||
#include "Input.h"
|
||||
#include "vncExtInit.h"
|
||||
#include "RFBGlue.h"
|
||||
|
||||
#include "inputstr.h"
|
||||
#if XORG >= 110
|
||||
#include "inpututils.h"
|
||||
#endif
|
||||
#include "mi.h"
|
||||
#include "mipointer.h"
|
||||
#include "exevents.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "xkbsrv.h"
|
||||
#include "xkbstr.h"
|
||||
#include "xserver-properties.h"
|
||||
extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
extern const unsigned short code_map_qnum_to_xorgevdev[];
|
||||
extern const unsigned int code_map_qnum_to_xorgevdev_len;
|
||||
extern const unsigned short code_map_qnum_to_xorgkbd[];
|
||||
extern const unsigned int code_map_qnum_to_xorgkbd_len;
|
||||
|
||||
#define BUTTONS 7
|
||||
|
||||
/* Event queue is shared between all devices. */
|
||||
#if XORG < 111
|
||||
static EventList *eventq = NULL;
|
||||
#endif
|
||||
|
||||
DeviceIntPtr vncKeyboardDev;
|
||||
DeviceIntPtr vncPointerDev;
|
||||
|
||||
static int oldButtonMask;
|
||||
static int cursorPosX, cursorPosY;
|
||||
|
||||
static const unsigned short *codeMap;
|
||||
static unsigned int codeMapLen;
|
||||
|
||||
static KeySym pressedKeys[256];
|
||||
|
||||
static int vncPointerProc(DeviceIntPtr pDevice, int onoff);
|
||||
static void vncKeyboardBell(int percent, DeviceIntPtr device,
|
||||
void * ctrl, int class);
|
||||
static int vncKeyboardProc(DeviceIntPtr pDevice, int onoff);
|
||||
|
||||
static void vncKeysymKeyboardEvent(KeySym keysym, int down);
|
||||
|
||||
#define LOG_NAME "Input"
|
||||
|
||||
#define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Init input device.
|
||||
* This has to be called after core pointer/keyboard
|
||||
* initialization which unfortunately is after extensions
|
||||
* initialization (which means we cannot call it in
|
||||
* vncExtensionInit(). Check InitExtensions(),
|
||||
* InitCoreDevices() and InitInput() calls in dix/main.c.
|
||||
* Instead we call it from XserverDesktop at an appropriate
|
||||
* time.
|
||||
*/
|
||||
void vncInitInputDevice(void)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if ((vncPointerDev != NULL) || (vncKeyboardDev != NULL))
|
||||
return;
|
||||
|
||||
/*
|
||||
* On Linux we try to provide the same key codes as Xorg with
|
||||
* the evdev driver. On other platforms we mimic the older
|
||||
* Xorg KBD driver.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
codeMap = code_map_qnum_to_xorgevdev;
|
||||
codeMapLen = code_map_qnum_to_xorgevdev_len;
|
||||
#else
|
||||
codeMap = code_map_qnum_to_xorgkbd;
|
||||
codeMapLen = code_map_qnum_to_xorgkbd_len;
|
||||
#endif
|
||||
|
||||
for (i = 0;i < 256;i++)
|
||||
pressedKeys[i] = NoSymbol;
|
||||
|
||||
ret = AllocDevicePair(serverClient, "KasmVNC",
|
||||
&vncPointerDev, &vncKeyboardDev,
|
||||
vncPointerProc, vncKeyboardProc,
|
||||
FALSE);
|
||||
|
||||
if (ret != Success)
|
||||
FatalError("Failed to initialize KasmVNC input devices\n");
|
||||
|
||||
if (ActivateDevice(vncPointerDev, TRUE) != Success ||
|
||||
ActivateDevice(vncKeyboardDev, TRUE) != Success)
|
||||
FatalError("Failed to activate KasmVNC devices\n");
|
||||
|
||||
if (!EnableDevice(vncPointerDev, TRUE) ||
|
||||
!EnableDevice(vncKeyboardDev, TRUE))
|
||||
FatalError("Failed to activate KasmVNC devices\n");
|
||||
|
||||
#if XORG < 111
|
||||
/* eventq is never free()-ed because it exists during server life. */
|
||||
if (eventq == NULL)
|
||||
GetEventList(&eventq);
|
||||
#endif
|
||||
|
||||
vncPrepareInputDevices();
|
||||
}
|
||||
|
||||
#if XORG < 111
|
||||
static void enqueueEvents(DeviceIntPtr dev, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
/*
|
||||
* Passing arguments in global variable eventq is probably not
|
||||
* good programming practise but in this case it is safe and
|
||||
* clear.
|
||||
*/
|
||||
mieqEnqueue(dev, (InternalEvent *) (eventq + i)->event);
|
||||
}
|
||||
}
|
||||
#endif /* XORG < 111 */
|
||||
|
||||
void vncPointerButtonAction(int buttonMask)
|
||||
{
|
||||
int i;
|
||||
#if XORG < 111
|
||||
int n;
|
||||
#endif
|
||||
#if XORG >= 110
|
||||
ValuatorMask mask;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < BUTTONS; i++) {
|
||||
if ((buttonMask ^ oldButtonMask) & (1 << i)) {
|
||||
int action = (buttonMask & (1<<i)) ?
|
||||
ButtonPress : ButtonRelease;
|
||||
#if XORG < 110
|
||||
n = GetPointerEvents(eventq, vncPointerDev,
|
||||
action, i + 1,
|
||||
POINTER_RELATIVE, 0, 0, NULL);
|
||||
enqueueEvents(vncPointerDev, n);
|
||||
#elif XORG < 111
|
||||
valuator_mask_set_range(&mask, 0, 0, NULL);
|
||||
n = GetPointerEvents(eventq, vncPointerDev,
|
||||
action, i + 1,
|
||||
POINTER_RELATIVE, &mask);
|
||||
enqueueEvents(vncPointerDev, n);
|
||||
#else
|
||||
valuator_mask_set_range(&mask, 0, 0, NULL);
|
||||
QueuePointerEvents(vncPointerDev, action, i + 1,
|
||||
POINTER_RELATIVE, &mask);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
oldButtonMask = buttonMask;
|
||||
}
|
||||
|
||||
void vncPointerMove(int x, int y)
|
||||
{
|
||||
int valuators[2];
|
||||
#if XORG < 111
|
||||
int n;
|
||||
#endif
|
||||
#if XORG >= 110
|
||||
ValuatorMask mask;
|
||||
#endif
|
||||
|
||||
if (cursorPosX == x && cursorPosY == y)
|
||||
return;
|
||||
|
||||
valuators[0] = x;
|
||||
valuators[1] = y;
|
||||
#if XORG < 110
|
||||
n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0,
|
||||
POINTER_ABSOLUTE, 0, 2, valuators);
|
||||
enqueueEvents(vncPointerDev, n);
|
||||
#elif XORG < 111
|
||||
valuator_mask_set_range(&mask, 0, 2, valuators);
|
||||
n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0,
|
||||
POINTER_ABSOLUTE, &mask);
|
||||
enqueueEvents(vncPointerDev, n);
|
||||
#else
|
||||
valuator_mask_set_range(&mask, 0, 2, valuators);
|
||||
QueuePointerEvents(vncPointerDev, MotionNotify, 0,
|
||||
POINTER_ABSOLUTE, &mask);
|
||||
#endif
|
||||
|
||||
cursorPosX = x;
|
||||
cursorPosY = y;
|
||||
}
|
||||
|
||||
void vncGetPointerPos(int *x, int *y)
|
||||
{
|
||||
if (vncPointerDev != NULL) {
|
||||
ScreenPtr ptrScreen;
|
||||
|
||||
miPointerGetPosition(vncPointerDev, &cursorPosX, &cursorPosY);
|
||||
|
||||
/* Pointer coordinates are screen relative */
|
||||
ptrScreen = miPointerGetScreen(vncPointerDev);
|
||||
cursorPosX += ptrScreen->x;
|
||||
cursorPosY += ptrScreen->y;
|
||||
}
|
||||
|
||||
*x = cursorPosX;
|
||||
*y = cursorPosY;
|
||||
}
|
||||
|
||||
static int vncPointerProc(DeviceIntPtr pDevice, int onoff)
|
||||
{
|
||||
BYTE map[BUTTONS + 1];
|
||||
DevicePtr pDev = (DevicePtr)pDevice;
|
||||
int i;
|
||||
/*
|
||||
* NOTE: map[] array is one element longer than btn_labels[] array. This
|
||||
* is not a bug.
|
||||
*/
|
||||
Atom btn_labels[BUTTONS];
|
||||
Atom axes_labels[2];
|
||||
|
||||
switch (onoff) {
|
||||
case DEVICE_INIT:
|
||||
for (i = 0; i < BUTTONS + 1; i++)
|
||||
map[i] = i;
|
||||
|
||||
btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
|
||||
btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
|
||||
btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
|
||||
btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
|
||||
btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
|
||||
btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
|
||||
btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
|
||||
|
||||
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
|
||||
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
|
||||
|
||||
InitPointerDeviceStruct(pDev, map, BUTTONS, btn_labels,
|
||||
(PtrCtrlProcPtr)NoopDDA,
|
||||
GetMotionHistorySize(),
|
||||
2, axes_labels);
|
||||
break;
|
||||
case DEVICE_ON:
|
||||
pDev->on = TRUE;
|
||||
break;
|
||||
case DEVICE_OFF:
|
||||
pDev->on = FALSE;
|
||||
break;
|
||||
case DEVICE_CLOSE:
|
||||
vncPointerDev = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void vncKeyboardBell(int percent, DeviceIntPtr device,
|
||||
void * ctrl, int class)
|
||||
{
|
||||
if (percent > 0)
|
||||
vncBell();
|
||||
}
|
||||
|
||||
static void vncKeyboardCtrl(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
|
||||
{
|
||||
vncSetLEDState(ctrl->leds);
|
||||
}
|
||||
|
||||
static int vncKeyboardProc(DeviceIntPtr pDevice, int onoff)
|
||||
{
|
||||
DevicePtr pDev = (DevicePtr)pDevice;
|
||||
|
||||
switch (onoff) {
|
||||
case DEVICE_INIT:
|
||||
InitKeyboardDeviceStruct(pDevice, NULL, vncKeyboardBell,
|
||||
vncKeyboardCtrl);
|
||||
break;
|
||||
case DEVICE_ON:
|
||||
pDev->on = TRUE;
|
||||
break;
|
||||
case DEVICE_OFF:
|
||||
pDev->on = FALSE;
|
||||
break;
|
||||
case DEVICE_CLOSE:
|
||||
vncKeyboardDev = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static inline void pressKey(DeviceIntPtr dev, int kc, Bool down, const char *msg)
|
||||
{
|
||||
int action;
|
||||
#if XORG < 111
|
||||
unsigned int n;
|
||||
#endif
|
||||
|
||||
if (msg != NULL)
|
||||
LOG_DEBUG("%s %d %s", msg, kc, down ? "down" : "up");
|
||||
|
||||
action = down ? KeyPress : KeyRelease;
|
||||
#if XORG < 111
|
||||
n = GetKeyboardEvents(eventq, dev, action, kc);
|
||||
enqueueEvents(dev, n);
|
||||
#elif XORG < 118
|
||||
QueueKeyboardEvents(dev, action, kc, NULL);
|
||||
#else
|
||||
QueueKeyboardEvents(dev, action, kc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* vncKeyboardEvent() - add X11 events for the given RFB key event
|
||||
*/
|
||||
void vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down)
|
||||
{
|
||||
/* Simple case: the client has specified the key */
|
||||
if (xtcode && xtcode < codeMapLen) {
|
||||
int keycode;
|
||||
|
||||
keycode = codeMap[xtcode];
|
||||
if (!keycode) {
|
||||
/*
|
||||
* Figure something out based on keysym if we
|
||||
* cannot find a mapping.
|
||||
*/
|
||||
if (keysym)
|
||||
vncKeysymKeyboardEvent(keysym, down);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We update the state table in case we get a mix of
|
||||
* events with and without key codes.
|
||||
*/
|
||||
if (down)
|
||||
pressedKeys[keycode] = keysym;
|
||||
else
|
||||
pressedKeys[keycode] = NoSymbol;
|
||||
|
||||
pressKey(vncKeyboardDev, keycode, down, "raw keycode");
|
||||
mieqProcessInputEvents();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advanced case: We have to figure out a sequence of keys that
|
||||
* result in the given keysym
|
||||
*/
|
||||
if (keysym)
|
||||
vncKeysymKeyboardEvent(keysym, down);
|
||||
}
|
||||
|
||||
/* altKeysym is a table of alternative keysyms which have the same meaning. */
|
||||
|
||||
static struct altKeysym_t {
|
||||
KeySym a, b;
|
||||
} altKeysym[] = {
|
||||
{ XK_Shift_L, XK_Shift_R },
|
||||
{ XK_Control_L, XK_Control_R },
|
||||
{ XK_Meta_L, XK_Meta_R },
|
||||
{ XK_Alt_L, XK_Alt_R },
|
||||
{ XK_Super_L, XK_Super_R },
|
||||
{ XK_Hyper_L, XK_Hyper_R },
|
||||
{ XK_KP_Space, XK_space },
|
||||
{ XK_KP_Tab, XK_Tab },
|
||||
{ XK_KP_Enter, XK_Return },
|
||||
{ XK_KP_F1, XK_F1 },
|
||||
{ XK_KP_F2, XK_F2 },
|
||||
{ XK_KP_F3, XK_F3 },
|
||||
{ XK_KP_F4, XK_F4 },
|
||||
{ XK_KP_Home, XK_Home },
|
||||
{ XK_KP_Left, XK_Left },
|
||||
{ XK_KP_Up, XK_Up },
|
||||
{ XK_KP_Right, XK_Right },
|
||||
{ XK_KP_Down, XK_Down },
|
||||
{ XK_KP_Page_Up, XK_Page_Up },
|
||||
{ XK_KP_Page_Down, XK_Page_Down },
|
||||
{ XK_KP_End, XK_End },
|
||||
{ XK_KP_Begin, XK_Begin },
|
||||
{ XK_KP_Insert, XK_Insert },
|
||||
{ XK_KP_Delete, XK_Delete },
|
||||
{ XK_KP_Equal, XK_equal },
|
||||
{ XK_KP_Multiply, XK_asterisk },
|
||||
{ XK_KP_Add, XK_plus },
|
||||
{ XK_KP_Separator, XK_comma },
|
||||
{ XK_KP_Subtract, XK_minus },
|
||||
{ XK_KP_Decimal, XK_period },
|
||||
{ XK_KP_Divide, XK_slash },
|
||||
{ XK_KP_0, XK_0 },
|
||||
{ XK_KP_1, XK_1 },
|
||||
{ XK_KP_2, XK_2 },
|
||||
{ XK_KP_3, XK_3 },
|
||||
{ XK_KP_4, XK_4 },
|
||||
{ XK_KP_5, XK_5 },
|
||||
{ XK_KP_6, XK_6 },
|
||||
{ XK_KP_7, XK_7 },
|
||||
{ XK_KP_8, XK_8 },
|
||||
{ XK_KP_9, XK_9 },
|
||||
{ XK_ISO_Level3_Shift, XK_Mode_switch },
|
||||
};
|
||||
|
||||
/*
|
||||
* vncKeysymKeyboardEvent() - work out the best keycode corresponding
|
||||
* to the keysym sent by the viewer. This is basically impossible in
|
||||
* the general case, but we make a best effort by assuming that all
|
||||
* useful keysyms can be reached using just the Shift and
|
||||
* Level 3 (AltGr) modifiers. For core keyboards this is basically
|
||||
* always true, and should be true for most sane, western XKB layouts.
|
||||
*/
|
||||
static void vncKeysymKeyboardEvent(KeySym keysym, int down)
|
||||
{
|
||||
int i;
|
||||
unsigned state, new_state;
|
||||
KeyCode keycode;
|
||||
|
||||
unsigned level_three_mask;
|
||||
KeyCode shift_press, level_three_press;
|
||||
KeyCode shift_release[8], level_three_release[8];
|
||||
size_t shift_release_count, level_three_release_count;
|
||||
|
||||
/*
|
||||
* Release events must match the press event, so look up what
|
||||
* keycode we sent for the press.
|
||||
*/
|
||||
if (!down) {
|
||||
for (i = 0;i < 256;i++) {
|
||||
if (pressedKeys[i] == keysym) {
|
||||
pressedKeys[i] = NoSymbol;
|
||||
pressKey(vncKeyboardDev, i, FALSE, "keycode");
|
||||
mieqProcessInputEvents();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen quite often as we ignore some
|
||||
* key presses.
|
||||
*/
|
||||
LOG_DEBUG("Unexpected release of keysym 0x%x", keysym);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we are checking the current state to determine if we need
|
||||
* to fake modifiers, we must make sure that everything put on the
|
||||
* input queue is processed before we start. Otherwise, shift may be
|
||||
* stuck down.
|
||||
*/
|
||||
mieqProcessInputEvents();
|
||||
|
||||
state = vncGetKeyboardState();
|
||||
|
||||
keycode = vncKeysymToKeycode(keysym, state, &new_state);
|
||||
|
||||
/* Try some equivalent keysyms if we couldn't find a perfect match */
|
||||
if (keycode == 0) {
|
||||
for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
|
||||
KeySym altsym;
|
||||
|
||||
if (altKeysym[i].a == keysym)
|
||||
altsym = altKeysym[i].b;
|
||||
else if (altKeysym[i].b == keysym)
|
||||
altsym = altKeysym[i].a;
|
||||
else
|
||||
continue;
|
||||
|
||||
keycode = vncKeysymToKeycode(altsym, state, &new_state);
|
||||
if (keycode != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* No matches. Will have to add a new entry... */
|
||||
if (keycode == 0) {
|
||||
keycode = vncAddKeysym(keysym, state);
|
||||
if (keycode == 0) {
|
||||
LOG_ERROR("Failure adding new keysym 0x%x", keysym);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("Added unknown keysym 0x%x to keycode %d",
|
||||
keysym, keycode);
|
||||
|
||||
/*
|
||||
* The state given to addKeysym() is just a hint and
|
||||
* the actual result might still require some state
|
||||
* changes.
|
||||
*/
|
||||
keycode = vncKeysymToKeycode(keysym, state, &new_state);
|
||||
if (keycode == 0) {
|
||||
LOG_ERROR("Newly added keysym 0x%x cannot be generated", keysym);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* X11 generally lets shift toggle the keys on the numeric pad
|
||||
* the same way NumLock does. This is however not the case on
|
||||
* other systems like Windows. As a result, some applications
|
||||
* get confused when we do a fake shift to get the same effect
|
||||
* that having NumLock active would produce.
|
||||
*
|
||||
* Until we have proper NumLock synchronisation (so we can
|
||||
* avoid faking shift), we try to avoid the fake shifts if we
|
||||
* can use an alternative keysym.
|
||||
*/
|
||||
if (((state & ShiftMask) != (new_state & ShiftMask)) &&
|
||||
vncGetAvoidShiftNumLock() && vncIsAffectedByNumLock(keycode)) {
|
||||
KeyCode keycode2;
|
||||
unsigned new_state2;
|
||||
|
||||
LOG_DEBUG("Finding alternative to keysym 0x%x to avoid fake shift for numpad", keysym);
|
||||
|
||||
for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
|
||||
KeySym altsym;
|
||||
|
||||
if (altKeysym[i].a == keysym)
|
||||
altsym = altKeysym[i].b;
|
||||
else if (altKeysym[i].b == keysym)
|
||||
altsym = altKeysym[i].a;
|
||||
else
|
||||
continue;
|
||||
|
||||
keycode2 = vncKeysymToKeycode(altsym, state, &new_state2);
|
||||
if (keycode2 == 0)
|
||||
continue;
|
||||
|
||||
if (((state & ShiftMask) != (new_state2 & ShiftMask)) &&
|
||||
vncIsAffectedByNumLock(keycode2))
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sizeof(altKeysym)/sizeof(altKeysym[0]))
|
||||
LOG_DEBUG("No alternative keysym found");
|
||||
else {
|
||||
keycode = keycode2;
|
||||
new_state = new_state2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "Shifted Tab" is a bit of a mess. Some systems have varying,
|
||||
* special keysyms for this symbol. VNC mandates that clients
|
||||
* should always send the plain XK_Tab keysym and the server
|
||||
* should deduce the meaning based on current Shift state.
|
||||
* To comply with this, we will find the keycode that sends
|
||||
* XK_Tab, and make sure that Shift isn't cleared. This can
|
||||
* possibly result in a different keysym than XK_Tab, but that
|
||||
* is the desired behaviour.
|
||||
*
|
||||
* Note: We never get ISO_Left_Tab here because it's already
|
||||
* been translated in VNCSConnectionST.
|
||||
*/
|
||||
if (keysym == XK_Tab && (state & ShiftMask))
|
||||
new_state |= ShiftMask;
|
||||
|
||||
/*
|
||||
* We need a bigger state change than just shift,
|
||||
* so we need to know what the mask is for level 3 shifts.
|
||||
*/
|
||||
if ((new_state & ~ShiftMask) != (state & ~ShiftMask))
|
||||
level_three_mask = vncGetLevelThreeMask();
|
||||
else
|
||||
level_three_mask = 0;
|
||||
|
||||
shift_press = level_three_press = 0;
|
||||
shift_release_count = level_three_release_count = 0;
|
||||
|
||||
/* Need a fake press or release of shift? */
|
||||
if (!(state & ShiftMask) && (new_state & ShiftMask)) {
|
||||
shift_press = vncPressShift();
|
||||
if (shift_press == 0) {
|
||||
LOG_ERROR("Unable to find a modifier key for Shift");
|
||||
return;
|
||||
}
|
||||
|
||||
pressKey(vncKeyboardDev, shift_press, TRUE, "temp shift");
|
||||
} else if ((state & ShiftMask) && !(new_state & ShiftMask)) {
|
||||
shift_release_count = vncReleaseShift(shift_release,
|
||||
sizeof(shift_release)/sizeof(*shift_release));
|
||||
if (shift_release_count == 0) {
|
||||
LOG_ERROR("Unable to find the modifier key(s) for releasing Shift");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0;i < shift_release_count;i++)
|
||||
pressKey(vncKeyboardDev, shift_release[i], FALSE, "temp shift");
|
||||
}
|
||||
|
||||
/* Need a fake press or release of level three shift? */
|
||||
if (!(state & level_three_mask) && (new_state & level_three_mask)) {
|
||||
level_three_press = vncPressLevelThree();
|
||||
if (level_three_press == 0) {
|
||||
LOG_ERROR("Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch");
|
||||
return;
|
||||
}
|
||||
|
||||
pressKey(vncKeyboardDev, level_three_press, TRUE, "temp level 3 shift");
|
||||
} else if ((state & level_three_mask) && !(new_state & level_three_mask)) {
|
||||
level_three_release_count = vncReleaseLevelThree(level_three_release,
|
||||
sizeof(level_three_release)/sizeof(*level_three_release));
|
||||
if (level_three_release_count == 0) {
|
||||
LOG_ERROR("Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0;i < level_three_release_count;i++)
|
||||
pressKey(vncKeyboardDev, level_three_release[i], FALSE, "temp level 3 shift");
|
||||
}
|
||||
|
||||
/* Now press the actual key */
|
||||
pressKey(vncKeyboardDev, keycode, TRUE, "keycode");
|
||||
|
||||
/* And store the mapping so that we can do a proper release later */
|
||||
for (i = 0;i < 256;i++) {
|
||||
if (i == keycode)
|
||||
continue;
|
||||
if (pressedKeys[i] == keysym) {
|
||||
LOG_ERROR("Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode);
|
||||
pressedKeys[i] = NoSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
pressedKeys[keycode] = keysym;
|
||||
|
||||
/* Undo any fake level three shift */
|
||||
if (level_three_press != 0)
|
||||
pressKey(vncKeyboardDev, level_three_press, FALSE, "temp level 3 shift");
|
||||
else if (level_three_release_count != 0) {
|
||||
for (i = 0;i < level_three_release_count;i++)
|
||||
pressKey(vncKeyboardDev, level_three_release[i], TRUE, "temp level 3 shift");
|
||||
}
|
||||
|
||||
/* Undo any fake shift */
|
||||
if (shift_press != 0)
|
||||
pressKey(vncKeyboardDev, shift_press, FALSE, "temp shift");
|
||||
else if (shift_release_count != 0) {
|
||||
for (i = 0;i < shift_release_count;i++)
|
||||
pressKey(vncKeyboardDev, shift_release[i], TRUE, "temp shift");
|
||||
}
|
||||
|
||||
/*
|
||||
* When faking a modifier we are putting a keycode (which can
|
||||
* currently activate the desired modifier) on the input
|
||||
* queue. A future modmap change can change the mapping so
|
||||
* that this keycode means something else entirely. Guard
|
||||
* against this by processing the queue now.
|
||||
*/
|
||||
mieqProcessInputEvents();
|
||||
}
|
||||
64
unix/xserver/hw/vnc/Input.h
Normal file
64
unix/xserver/hw/vnc/Input.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* Copyright (C) 2009 TightVNC Team
|
||||
* Copyright (C) 2009, 2010 Red Hat, Inc.
|
||||
* Copyright (C) 2009, 2010 TigerVNC Team
|
||||
* Copyright 2013-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
/* Make sure macro doesn't conflict with macro in include/input.h. */
|
||||
#ifndef INPUT_H_
|
||||
#define INPUT_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <X11/X.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void vncInitInputDevice(void);
|
||||
|
||||
void vncPointerButtonAction(int buttonMask);
|
||||
void vncPointerMove(int x, int y);
|
||||
void vncGetPointerPos(int *x, int *y);
|
||||
|
||||
void vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down);
|
||||
|
||||
/* Backend dependent functions below here */
|
||||
|
||||
void vncPrepareInputDevices(void);
|
||||
|
||||
unsigned vncGetKeyboardState(void);
|
||||
unsigned vncGetLevelThreeMask(void);
|
||||
|
||||
KeyCode vncPressShift(void);
|
||||
size_t vncReleaseShift(KeyCode *keys, size_t maxKeys);
|
||||
|
||||
KeyCode vncPressLevelThree(void);
|
||||
size_t vncReleaseLevelThree(KeyCode *keys, size_t maxKeys);
|
||||
|
||||
KeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);
|
||||
|
||||
int vncIsAffectedByNumLock(KeyCode keycode);
|
||||
|
||||
KeyCode vncAddKeysym(KeySym keysym, unsigned state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
646
unix/xserver/hw/vnc/InputXKB.c
Normal file
646
unix/xserver/hw/vnc/InputXKB.c
Normal file
@@ -0,0 +1,646 @@
|
||||
/* Copyright (C) 2009 TightVNC Team
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
* Copyright 2013-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "xorg-version.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "xkbsrv.h"
|
||||
#include "xkbstr.h"
|
||||
#include "eventstr.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "mi.h"
|
||||
|
||||
#include "Input.h"
|
||||
|
||||
#ifndef KEYBOARD_OR_FLOAT
|
||||
#define KEYBOARD_OR_FLOAT MASTER_KEYBOARD
|
||||
#endif
|
||||
|
||||
#if XORG < 118
|
||||
#if XORG < 110
|
||||
#define GetMaster(dev, type) ((dev)->u.master)
|
||||
#else
|
||||
#define GetMaster(dev, type) ((dev)->master)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern DeviceIntPtr vncKeyboardDev;
|
||||
|
||||
static void vncXkbProcessDeviceEvent(int screenNum,
|
||||
InternalEvent *event,
|
||||
DeviceIntPtr dev);
|
||||
|
||||
/* Stolen from libX11 */
|
||||
static Bool
|
||||
XkbTranslateKeyCode(register XkbDescPtr xkb, KeyCode key,
|
||||
register unsigned int mods, unsigned int *mods_rtrn,
|
||||
KeySym *keysym_rtrn)
|
||||
{
|
||||
XkbKeyTypeRec *type;
|
||||
int col,nKeyGroups;
|
||||
unsigned preserve,effectiveGroup;
|
||||
KeySym *syms;
|
||||
|
||||
if (mods_rtrn!=NULL)
|
||||
*mods_rtrn = 0;
|
||||
|
||||
nKeyGroups= XkbKeyNumGroups(xkb,key);
|
||||
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
|
||||
if (keysym_rtrn!=NULL)
|
||||
*keysym_rtrn = NoSymbol;
|
||||
return False;
|
||||
}
|
||||
|
||||
syms = XkbKeySymsPtr(xkb,key);
|
||||
|
||||
/* find the offset of the effective group */
|
||||
col = 0;
|
||||
effectiveGroup= XkbGroupForCoreState(mods);
|
||||
if ( effectiveGroup>=nKeyGroups ) {
|
||||
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
||||
switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
||||
default:
|
||||
effectiveGroup %= nKeyGroups;
|
||||
break;
|
||||
case XkbClampIntoRange:
|
||||
effectiveGroup = nKeyGroups-1;
|
||||
break;
|
||||
case XkbRedirectIntoRange:
|
||||
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
||||
if (effectiveGroup>=nKeyGroups)
|
||||
effectiveGroup= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
|
||||
type = XkbKeyKeyType(xkb,key,effectiveGroup);
|
||||
|
||||
preserve= 0;
|
||||
if (type->map) { /* find the column (shift level) within the group */
|
||||
register int i;
|
||||
register XkbKTMapEntryPtr entry;
|
||||
for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
|
||||
if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
|
||||
col+= entry->level;
|
||||
if (type->preserve)
|
||||
preserve= type->preserve[i].mask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keysym_rtrn!=NULL)
|
||||
*keysym_rtrn= syms[col];
|
||||
if (mods_rtrn)
|
||||
*mods_rtrn= type->mods.mask&(~preserve);
|
||||
|
||||
return (syms[col]!=NoSymbol);
|
||||
}
|
||||
|
||||
static XkbAction *XkbKeyActionPtr(XkbDescPtr xkb, KeyCode key, unsigned int mods)
|
||||
{
|
||||
XkbKeyTypeRec *type;
|
||||
int col,nKeyGroups;
|
||||
unsigned effectiveGroup;
|
||||
XkbAction *acts;
|
||||
|
||||
if (!XkbKeyHasActions(xkb, key))
|
||||
return NULL;
|
||||
|
||||
nKeyGroups= XkbKeyNumGroups(xkb,key);
|
||||
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
|
||||
return NULL;
|
||||
|
||||
acts = XkbKeyActionsPtr(xkb,key);
|
||||
|
||||
/* find the offset of the effective group */
|
||||
col = 0;
|
||||
effectiveGroup= XkbGroupForCoreState(mods);
|
||||
if ( effectiveGroup>=nKeyGroups ) {
|
||||
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
||||
switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
||||
default:
|
||||
effectiveGroup %= nKeyGroups;
|
||||
break;
|
||||
case XkbClampIntoRange:
|
||||
effectiveGroup = nKeyGroups-1;
|
||||
break;
|
||||
case XkbRedirectIntoRange:
|
||||
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
||||
if (effectiveGroup>=nKeyGroups)
|
||||
effectiveGroup= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
|
||||
type = XkbKeyKeyType(xkb,key,effectiveGroup);
|
||||
|
||||
if (type->map) { /* find the column (shift level) within the group */
|
||||
register int i;
|
||||
register XkbKTMapEntryPtr entry;
|
||||
for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
|
||||
if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
|
||||
col+= entry->level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &acts[col];
|
||||
}
|
||||
|
||||
static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods)
|
||||
{
|
||||
int nKeyGroups;
|
||||
unsigned effectiveGroup;
|
||||
|
||||
nKeyGroups= XkbKeyNumGroups(xkb,key);
|
||||
if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
|
||||
return 0;
|
||||
|
||||
effectiveGroup= XkbGroupForCoreState(mods);
|
||||
if ( effectiveGroup>=nKeyGroups ) {
|
||||
unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
||||
switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
||||
default:
|
||||
effectiveGroup %= nKeyGroups;
|
||||
break;
|
||||
case XkbClampIntoRange:
|
||||
effectiveGroup = nKeyGroups-1;
|
||||
break;
|
||||
case XkbRedirectIntoRange:
|
||||
effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
||||
if (effectiveGroup>=nKeyGroups)
|
||||
effectiveGroup= 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return effectiveGroup;
|
||||
}
|
||||
|
||||
void vncPrepareInputDevices(void)
|
||||
{
|
||||
/*
|
||||
* Not ideal since these callbacks do not stack, but it's the only
|
||||
* decent way we can reliably catch events for both the slave and
|
||||
* master device.
|
||||
*/
|
||||
mieqSetHandler(ET_KeyPress, vncXkbProcessDeviceEvent);
|
||||
mieqSetHandler(ET_KeyRelease, vncXkbProcessDeviceEvent);
|
||||
}
|
||||
|
||||
unsigned vncGetKeyboardState(void)
|
||||
{
|
||||
DeviceIntPtr master;
|
||||
|
||||
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
||||
return XkbStateFieldFromRec(&master->key->xkbInfo->state);
|
||||
}
|
||||
|
||||
unsigned vncGetLevelThreeMask(void)
|
||||
{
|
||||
unsigned state;
|
||||
KeyCode keycode;
|
||||
XkbDescPtr xkb;
|
||||
XkbAction *act;
|
||||
|
||||
/* Group state is still important */
|
||||
state = vncGetKeyboardState();
|
||||
state &= ~0xff;
|
||||
|
||||
keycode = vncKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
|
||||
if (keycode == 0) {
|
||||
keycode = vncKeysymToKeycode(XK_Mode_switch, state, NULL);
|
||||
if (keycode == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, keycode, state);
|
||||
if (act == NULL)
|
||||
return 0;
|
||||
if (act->type != XkbSA_SetMods)
|
||||
return 0;
|
||||
|
||||
if (act->mods.flags & XkbSA_UseModMapMods)
|
||||
return xkb->map->modmap[keycode];
|
||||
else
|
||||
return act->mods.mask;
|
||||
}
|
||||
|
||||
KeyCode vncPressShift(void)
|
||||
{
|
||||
unsigned state;
|
||||
|
||||
XkbDescPtr xkb;
|
||||
unsigned int key;
|
||||
|
||||
state = vncGetKeyboardState();
|
||||
if (state & ShiftMask)
|
||||
return 0;
|
||||
|
||||
xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
|
||||
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
||||
XkbAction *act;
|
||||
unsigned char mask;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, key, state);
|
||||
if (act == NULL)
|
||||
continue;
|
||||
|
||||
if (act->type != XkbSA_SetMods)
|
||||
continue;
|
||||
|
||||
if (act->mods.flags & XkbSA_UseModMapMods)
|
||||
mask = xkb->map->modmap[key];
|
||||
else
|
||||
mask = act->mods.mask;
|
||||
|
||||
if ((mask & ShiftMask) == ShiftMask)
|
||||
return key;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t vncReleaseShift(KeyCode *keys, size_t maxKeys)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
unsigned state;
|
||||
|
||||
DeviceIntPtr master;
|
||||
XkbDescPtr xkb;
|
||||
unsigned int key;
|
||||
|
||||
state = vncGetKeyboardState();
|
||||
if (!(state & ShiftMask))
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
|
||||
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
||||
xkb = master->key->xkbInfo->desc;
|
||||
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
||||
XkbAction *act;
|
||||
unsigned char mask;
|
||||
|
||||
if (!key_is_down(master, key, KEY_PROCESSED))
|
||||
continue;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, key, state);
|
||||
if (act == NULL)
|
||||
continue;
|
||||
|
||||
if (act->type != XkbSA_SetMods)
|
||||
continue;
|
||||
|
||||
if (act->mods.flags & XkbSA_UseModMapMods)
|
||||
mask = xkb->map->modmap[key];
|
||||
else
|
||||
mask = act->mods.mask;
|
||||
|
||||
if (!(mask & ShiftMask))
|
||||
continue;
|
||||
|
||||
if (count >= maxKeys)
|
||||
return 0;
|
||||
|
||||
keys[count++] = key;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
KeyCode vncPressLevelThree(void)
|
||||
{
|
||||
unsigned state, mask;
|
||||
|
||||
KeyCode keycode;
|
||||
XkbDescPtr xkb;
|
||||
XkbAction *act;
|
||||
|
||||
mask = vncGetLevelThreeMask();
|
||||
if (mask == 0)
|
||||
return 0;
|
||||
|
||||
state = vncGetKeyboardState();
|
||||
if (state & mask)
|
||||
return 0;
|
||||
|
||||
keycode = vncKeysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
|
||||
if (keycode == 0) {
|
||||
keycode = vncKeysymToKeycode(XK_Mode_switch, state, NULL);
|
||||
if (keycode == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, keycode, state);
|
||||
if (act == NULL)
|
||||
return 0;
|
||||
if (act->type != XkbSA_SetMods)
|
||||
return 0;
|
||||
|
||||
return keycode;
|
||||
}
|
||||
|
||||
size_t vncReleaseLevelThree(KeyCode *keys, size_t maxKeys)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
unsigned state, mask;
|
||||
|
||||
DeviceIntPtr master;
|
||||
XkbDescPtr xkb;
|
||||
unsigned int key;
|
||||
|
||||
mask = vncGetLevelThreeMask();
|
||||
if (mask == 0)
|
||||
return 0;
|
||||
|
||||
state = vncGetKeyboardState();
|
||||
if (!(state & mask))
|
||||
return 0;
|
||||
|
||||
count = 0;
|
||||
|
||||
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
||||
xkb = master->key->xkbInfo->desc;
|
||||
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
||||
XkbAction *act;
|
||||
unsigned char key_mask;
|
||||
|
||||
if (!key_is_down(master, key, KEY_PROCESSED))
|
||||
continue;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, key, state);
|
||||
if (act == NULL)
|
||||
continue;
|
||||
|
||||
if (act->type != XkbSA_SetMods)
|
||||
continue;
|
||||
|
||||
if (act->mods.flags & XkbSA_UseModMapMods)
|
||||
key_mask = xkb->map->modmap[key];
|
||||
else
|
||||
key_mask = act->mods.mask;
|
||||
|
||||
if (!(key_mask & mask))
|
||||
continue;
|
||||
|
||||
if (count >= maxKeys)
|
||||
return 0;
|
||||
|
||||
keys[count++] = key;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
KeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state)
|
||||
{
|
||||
XkbDescPtr xkb;
|
||||
unsigned int key;
|
||||
KeySym ks;
|
||||
unsigned level_three_mask;
|
||||
|
||||
if (new_state != NULL)
|
||||
*new_state = state;
|
||||
|
||||
xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
|
||||
for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
||||
unsigned int state_out;
|
||||
KeySym dummy;
|
||||
|
||||
XkbTranslateKeyCode(xkb, key, state, &state_out, &ks);
|
||||
if (ks == NoSymbol)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Despite every known piece of documentation on
|
||||
* XkbTranslateKeyCode() stating that mods_rtrn returns
|
||||
* the unconsumed modifiers, in reality it always
|
||||
* returns the _potentially consumed_ modifiers.
|
||||
*/
|
||||
state_out = state & ~state_out;
|
||||
if (state_out & LockMask)
|
||||
XkbConvertCase(ks, &dummy, &ks);
|
||||
|
||||
if (ks == keysym)
|
||||
return key;
|
||||
}
|
||||
|
||||
if (new_state == NULL)
|
||||
return 0;
|
||||
|
||||
*new_state = (state & ~ShiftMask) |
|
||||
((state & ShiftMask) ? 0 : ShiftMask);
|
||||
key = vncKeysymToKeycode(keysym, *new_state, NULL);
|
||||
if (key != 0)
|
||||
return key;
|
||||
|
||||
level_three_mask = vncGetLevelThreeMask();
|
||||
if (level_three_mask == 0)
|
||||
return 0;
|
||||
|
||||
*new_state = (state & ~level_three_mask) |
|
||||
((state & level_three_mask) ? 0 : level_three_mask);
|
||||
key = vncKeysymToKeycode(keysym, *new_state, NULL);
|
||||
if (key != 0)
|
||||
return key;
|
||||
|
||||
*new_state = (state & ~(ShiftMask | level_three_mask)) |
|
||||
((state & ShiftMask) ? 0 : ShiftMask) |
|
||||
((state & level_three_mask) ? 0 : level_three_mask);
|
||||
key = vncKeysymToKeycode(keysym, *new_state, NULL);
|
||||
if (key != 0)
|
||||
return key;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncIsAffectedByNumLock(KeyCode keycode)
|
||||
{
|
||||
unsigned state;
|
||||
|
||||
KeyCode numlock_keycode;
|
||||
unsigned numlock_mask;
|
||||
|
||||
XkbDescPtr xkb;
|
||||
XkbAction *act;
|
||||
|
||||
unsigned group;
|
||||
XkbKeyTypeRec *type;
|
||||
|
||||
/* Group state is still important */
|
||||
state = vncGetKeyboardState();
|
||||
state &= ~0xff;
|
||||
|
||||
/*
|
||||
* Not sure if hunting for a virtual modifier called "NumLock",
|
||||
* or following the keysym Num_Lock is the best approach. We
|
||||
* try the latter.
|
||||
*/
|
||||
numlock_keycode = vncKeysymToKeycode(XK_Num_Lock, state, NULL);
|
||||
if (numlock_keycode == 0)
|
||||
return 0;
|
||||
|
||||
xkb = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT)->key->xkbInfo->desc;
|
||||
|
||||
act = XkbKeyActionPtr(xkb, numlock_keycode, state);
|
||||
if (act == NULL)
|
||||
return 0;
|
||||
if (act->type != XkbSA_LockMods)
|
||||
return 0;
|
||||
|
||||
if (act->mods.flags & XkbSA_UseModMapMods)
|
||||
numlock_mask = xkb->map->modmap[keycode];
|
||||
else
|
||||
numlock_mask = act->mods.mask;
|
||||
|
||||
group = XkbKeyEffectiveGroup(xkb, keycode, state);
|
||||
type = XkbKeyKeyType(xkb, keycode, group);
|
||||
if ((type->mods.mask & numlock_mask) == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
KeyCode vncAddKeysym(KeySym keysym, unsigned state)
|
||||
{
|
||||
DeviceIntPtr master;
|
||||
XkbDescPtr xkb;
|
||||
unsigned int key;
|
||||
|
||||
XkbEventCauseRec cause;
|
||||
XkbChangesRec changes;
|
||||
|
||||
int types[1];
|
||||
KeySym *syms;
|
||||
KeySym upper, lower;
|
||||
|
||||
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
||||
xkb = master->key->xkbInfo->desc;
|
||||
for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
|
||||
if (XkbKeyNumGroups(xkb, key) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (key < xkb->min_key_code)
|
||||
return 0;
|
||||
|
||||
memset(&changes, 0, sizeof(changes));
|
||||
memset(&cause, 0, sizeof(cause));
|
||||
|
||||
XkbSetCauseUnknown(&cause);
|
||||
|
||||
/*
|
||||
* Tools like xkbcomp get confused if there isn't a name
|
||||
* assigned to the keycode we're trying to use.
|
||||
*/
|
||||
if (xkb->names && xkb->names->keys &&
|
||||
(xkb->names->keys[key].name[0] == '\0')) {
|
||||
xkb->names->keys[key].name[0] = 'I';
|
||||
xkb->names->keys[key].name[1] = '0' + (key / 100) % 10;
|
||||
xkb->names->keys[key].name[2] = '0' + (key / 10) % 10;
|
||||
xkb->names->keys[key].name[3] = '0' + (key / 1) % 10;
|
||||
|
||||
changes.names.changed |= XkbKeyNamesMask;
|
||||
changes.names.first_key = key;
|
||||
changes.names.num_keys = 1;
|
||||
}
|
||||
|
||||
/* FIXME: Verify that ONE_LEVEL/ALPHABETIC isn't screwed up */
|
||||
|
||||
/*
|
||||
* For keysyms that are affected by Lock, we are better off
|
||||
* using ALPHABETIC rather than ONE_LEVEL as the latter
|
||||
* generally cannot produce lower case when Lock is active.
|
||||
*/
|
||||
XkbConvertCase(keysym, &lower, &upper);
|
||||
if (upper == lower)
|
||||
types[XkbGroup1Index] = XkbOneLevelIndex;
|
||||
else
|
||||
types[XkbGroup1Index] = XkbAlphabeticIndex;
|
||||
|
||||
XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes.map);
|
||||
|
||||
syms = XkbKeySymsPtr(xkb,key);
|
||||
if (upper == lower)
|
||||
syms[0] = keysym;
|
||||
else {
|
||||
syms[0] = lower;
|
||||
syms[1] = upper;
|
||||
}
|
||||
|
||||
changes.map.changed |= XkbKeySymsMask;
|
||||
changes.map.first_key_sym = key;
|
||||
changes.map.num_key_syms = 1;
|
||||
|
||||
XkbSendNotification(master, &changes, &cause);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static void vncXkbProcessDeviceEvent(int screenNum,
|
||||
InternalEvent *event,
|
||||
DeviceIntPtr dev)
|
||||
{
|
||||
unsigned int backupctrls;
|
||||
XkbControlsPtr ctrls;
|
||||
|
||||
if (event->device_event.sourceid != vncKeyboardDev->id) {
|
||||
dev->public.processInputProc(event, dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to bypass AccessX since it is timing sensitive and
|
||||
* the network can cause fake event delays.
|
||||
*/
|
||||
ctrls = dev->key->xkbInfo->desc->ctrls;
|
||||
backupctrls = ctrls->enabled_ctrls;
|
||||
ctrls->enabled_ctrls &= ~XkbAllFilteredEventsMask;
|
||||
|
||||
/*
|
||||
* This flag needs to be set for key repeats to be properly
|
||||
* respected.
|
||||
*/
|
||||
if ((event->device_event.type == ET_KeyPress) &&
|
||||
key_is_down(dev, event->device_event.detail.key, KEY_PROCESSED))
|
||||
event->device_event.key_repeat = TRUE;
|
||||
|
||||
dev->public.processInputProc(event, dev);
|
||||
|
||||
ctrls->enabled_ctrls = backupctrls;
|
||||
}
|
||||
73
unix/xserver/hw/vnc/Makefile.am
Normal file
73
unix/xserver/hw/vnc/Makefile.am
Normal file
@@ -0,0 +1,73 @@
|
||||
KASMVNC_SRCDIR=${top_srcdir}/../..
|
||||
KASMVNC_BUILDDIR=${KASMVNC_SRCDIR}
|
||||
|
||||
RFB_LIB=$(KASMVNC_BUILDDIR)/common/rfb/librfb.la
|
||||
RDR_LIB=$(KASMVNC_BUILDDIR)/common/rdr/librdr.la
|
||||
OS_LIB=$(KASMVNC_BUILDDIR)/common/os/libos.la
|
||||
NETWORK_LIB=$(KASMVNC_BUILDDIR)/common/network/libnetwork.la
|
||||
XREGION_LIB=$(KASMVNC_BUILDDIR)/common/Xregion/libXregion.la
|
||||
UNIXCOMMON_LIB=$(KASMVNC_BUILDDIR)/unix/common/libunixcommon.la
|
||||
COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB) $(OS_LIB) $(UNIXCOMMON_LIB)
|
||||
|
||||
noinst_LTLIBRARIES = libvnccommon.la
|
||||
|
||||
HDRS = vncExtInit.h vncHooks.h \
|
||||
vncBlockHandler.h vncSelection.h \
|
||||
XorgGlue.h XserverDesktop.h xorg-version.h \
|
||||
Input.h RFBGlue.h
|
||||
|
||||
libvnccommon_la_SOURCES = $(HDRS) \
|
||||
vncExt.c vncExtInit.cc vncHooks.c vncSelection.c \
|
||||
vncBlockHandler.c XorgGlue.c RandrGlue.c RFBGlue.cc XserverDesktop.cc \
|
||||
Input.c InputXKB.c qnum_to_xorgevdev.c qnum_to_xorgkbd.c
|
||||
|
||||
libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" -I$(KASMVNC_SRCDIR)/unix/common \
|
||||
-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(KASMVNC_SRCDIR)/common -UHAVE_CONFIG_H \
|
||||
-I$(KASMVNC_SRCDIR)/unix/vncconfig $(XVNC_CPPFLAGS) ${XSERVERLIBS_CFLAGS} -I$(includedir) \
|
||||
-I$(top_srcdir)/include
|
||||
|
||||
bin_PROGRAMS = Xvnc
|
||||
|
||||
man1_MANS = Xvnc.man
|
||||
|
||||
Xvnc_SOURCES = xvnc.c \
|
||||
$(top_srcdir)/Xi/stubs.c $(top_srcdir)/mi/miinitext.c \
|
||||
$(top_srcdir)/fb/fbcmap_mi.c buildtime.c
|
||||
|
||||
# Xvnc contains no C++ sources so automake doesn't understand that we
|
||||
# need to use the C++ compiler to link things. This is the upstream
|
||||
# recommendation for coaxing automake.
|
||||
nodist_EXTRA_Xvnc_SOURCES = dummy.cxx
|
||||
|
||||
Xvnc_CPPFLAGS = $(XVNC_CPPFLAGS) -DKASMVNC -DNO_MODULE_EXTS \
|
||||
-UHAVE_CONFIG_H \
|
||||
-DXFree86Server -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
|
||||
-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(KASMVNC_SRCDIR)/common -I$(KASMVNC_SRCDIR)/unix/common \
|
||||
-I$(top_srcdir)/include ${XSERVERLIBS_CFLAGS} -I$(includedir)
|
||||
|
||||
Xvnc_LDADD = $(XVNC_LIBS) libvnccommon.la $(COMMON_LIBS) \
|
||||
$(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XVNC_SYS_LIBS) -lX11 -lwebp -lssl -lcrypto
|
||||
|
||||
Xvnc_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG) -fopenmp
|
||||
|
||||
libvnc_la_LTLIBRARIES = libvnc.la
|
||||
libvnc_ladir = $(moduledir)/extensions
|
||||
|
||||
libvnc_la_SOURCES = vncModule.c
|
||||
|
||||
# See Xvnc magic above
|
||||
nodist_EXTRA_libvnc_la_SOURCES = dummy.cxx
|
||||
|
||||
libvnc_la_CPPFLAGS = $(XVNC_CPPFLAGS) -I$(KASMVNC_SRCDIR)/common -UHAVE_CONFIG_H \
|
||||
-I$(KASMVNC_SRCDIR)/unix/common \
|
||||
-I$(top_srcdir)/hw/xfree86/common \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support/bus \
|
||||
-I$(top_srcdir)/include \
|
||||
${XSERVERLIBS_CFLAGS} -I$(includedir)
|
||||
|
||||
libvnc_la_LDFLAGS = -module -avoid-version -Wl,-z,now
|
||||
|
||||
libvnc_la_LIBADD = libvnccommon.la $(COMMON_LIBS)
|
||||
|
||||
EXTRA_DIST = Xvnc.man
|
||||
212
unix/xserver/hw/vnc/RFBGlue.cc
Normal file
212
unix/xserver/hw/vnc/RFBGlue.cc
Normal file
@@ -0,0 +1,212 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <network/TcpSocket.h>
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <rfb/Logger_stdio.h>
|
||||
#include <rfb/Logger_syslog.h>
|
||||
|
||||
#include "RFBGlue.h"
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
// Loggers used by C code must be created here
|
||||
static LogWriter inputLog("Input");
|
||||
static LogWriter selectionLog("Selection");
|
||||
|
||||
void vncInitRFB(void)
|
||||
{
|
||||
rfb::initStdIOLoggers();
|
||||
rfb::initSyslogLogger();
|
||||
rfb::LogWriter::setLogParams("*:stderr:30");
|
||||
rfb::Configuration::enableServerParams();
|
||||
}
|
||||
|
||||
void vncLogError(const char *name, const char *format, ...)
|
||||
{
|
||||
LogWriter *vlog;
|
||||
va_list ap;
|
||||
vlog = LogWriter::getLogWriter(name);
|
||||
if (vlog == NULL)
|
||||
return;
|
||||
va_start(ap, format);
|
||||
vlog->verror(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void vncLogStatus(const char *name, const char *format, ...)
|
||||
{
|
||||
LogWriter *vlog;
|
||||
va_list ap;
|
||||
vlog = LogWriter::getLogWriter(name);
|
||||
if (vlog == NULL)
|
||||
return;
|
||||
va_start(ap, format);
|
||||
vlog->vstatus(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void vncLogInfo(const char *name, const char *format, ...)
|
||||
{
|
||||
LogWriter *vlog;
|
||||
va_list ap;
|
||||
vlog = LogWriter::getLogWriter(name);
|
||||
if (vlog == NULL)
|
||||
return;
|
||||
va_start(ap, format);
|
||||
vlog->vinfo(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void vncLogDebug(const char *name, const char *format, ...)
|
||||
{
|
||||
LogWriter *vlog;
|
||||
va_list ap;
|
||||
vlog = LogWriter::getLogWriter(name);
|
||||
if (vlog == NULL)
|
||||
return;
|
||||
va_start(ap, format);
|
||||
vlog->vdebug(format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int vncSetParam(const char *name, const char *value)
|
||||
{
|
||||
if (value != NULL)
|
||||
return rfb::Configuration::setParam(name, value);
|
||||
else {
|
||||
VoidParameter *param;
|
||||
param = rfb::Configuration::getParam(name);
|
||||
if (param == NULL)
|
||||
return false;
|
||||
return param->setParam();
|
||||
}
|
||||
}
|
||||
|
||||
int vncSetParamSimple(const char *nameAndValue)
|
||||
{
|
||||
return rfb::Configuration::setParam(nameAndValue);
|
||||
}
|
||||
|
||||
char* vncGetParam(const char *name)
|
||||
{
|
||||
rfb::VoidParameter *param;
|
||||
char *value;
|
||||
char *ret;
|
||||
|
||||
// Hack to avoid exposing password!
|
||||
if (strcasecmp(name, "Password") == 0)
|
||||
return NULL;
|
||||
|
||||
param = rfb::Configuration::getParam(name);
|
||||
if (param == NULL)
|
||||
return NULL;
|
||||
|
||||
value = param->getValueStr();
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = strdup(value);
|
||||
|
||||
delete [] value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* vncGetParamDesc(const char *name)
|
||||
{
|
||||
rfb::VoidParameter *param;
|
||||
|
||||
param = rfb::Configuration::getParam(name);
|
||||
if (param == NULL)
|
||||
return NULL;
|
||||
|
||||
return param->getDescription();
|
||||
}
|
||||
|
||||
int vncGetParamCount(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
for (ParameterIterator i; i.param; i.next())
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
char *vncGetParamList(void)
|
||||
{
|
||||
int len;
|
||||
char *data, *ptr;
|
||||
|
||||
len = 0;
|
||||
|
||||
for (ParameterIterator i; i.param; i.next()) {
|
||||
int l = strlen(i.param->getName());
|
||||
if (l <= 255)
|
||||
len += l + 1;
|
||||
}
|
||||
|
||||
data = (char*)malloc(len + 1);
|
||||
if (data == NULL)
|
||||
return NULL;
|
||||
|
||||
ptr = data;
|
||||
for (ParameterIterator i; i.param; i.next()) {
|
||||
int l = strlen(i.param->getName());
|
||||
if (l <= 255) {
|
||||
*ptr++ = l;
|
||||
memcpy(ptr, i.param->getName(), l);
|
||||
ptr += l;
|
||||
}
|
||||
}
|
||||
*ptr = '\0';
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void vncListParams(int width, int nameWidth)
|
||||
{
|
||||
rfb::Configuration::listParams(width, nameWidth);
|
||||
}
|
||||
|
||||
int vncGetSocketPort(int fd)
|
||||
{
|
||||
return network::getSockPort(fd);
|
||||
}
|
||||
|
||||
int vncIsTCPPortUsed(int port)
|
||||
{
|
||||
try {
|
||||
// Attempt to create TCPListeners on that port.
|
||||
std::list<network::SocketListener*> dummy;
|
||||
network::createTcpListeners (&dummy, 0, port);
|
||||
while (!dummy.empty()) {
|
||||
delete dummy.back();
|
||||
dummy.pop_back();
|
||||
}
|
||||
} catch (rdr::Exception& e) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
56
unix/xserver/hw/vnc/RFBGlue.h
Normal file
56
unix/xserver/hw/vnc/RFBGlue.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef RFB_GLUE_H
|
||||
#define RFB_GLUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void vncInitRFB(void);
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define __printf_attr(a, b) __attribute__((__format__ (__printf__, a, b)))
|
||||
#else
|
||||
# define __printf_attr(a, b)
|
||||
#endif // __GNUC__
|
||||
|
||||
void vncLogError(const char *name, const char *format, ...) __printf_attr(2, 3);
|
||||
void vncLogStatus(const char *name, const char *format, ...) __printf_attr(2, 3);
|
||||
void vncLogInfo(const char *name, const char *format, ...) __printf_attr(2, 3);
|
||||
void vncLogDebug(const char *name, const char *format, ...) __printf_attr(2, 3);
|
||||
|
||||
int vncSetParam(const char *name, const char *value);
|
||||
int vncSetParamSimple(const char *nameAndValue);
|
||||
char* vncGetParam(const char *name);
|
||||
const char* vncGetParamDesc(const char *name);
|
||||
|
||||
int vncGetParamCount(void);
|
||||
char *vncGetParamList(void);
|
||||
void vncListParams(int width, int nameWidth);
|
||||
|
||||
int vncGetSocketPort(int fd);
|
||||
int vncIsTCPPortUsed(int port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
360
unix/xserver/hw/vnc/RandrGlue.c
Normal file
360
unix/xserver/hw/vnc/RandrGlue.c
Normal file
@@ -0,0 +1,360 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "scrnintstr.h"
|
||||
#include "randrstr.h"
|
||||
|
||||
#include "RandrGlue.h"
|
||||
#include "XorgGlue.h"
|
||||
|
||||
static int scrIdx;
|
||||
|
||||
void vncSetGlueContext(int screenIndex);
|
||||
|
||||
void vncSetGlueContext(int screenIndex)
|
||||
{
|
||||
scrIdx = screenIndex;
|
||||
}
|
||||
|
||||
int vncGetScreenWidth(void)
|
||||
{
|
||||
return screenInfo.screens[scrIdx]->width;
|
||||
}
|
||||
|
||||
int vncGetScreenHeight(void)
|
||||
{
|
||||
return screenInfo.screens[scrIdx]->height;
|
||||
}
|
||||
|
||||
int vncRandRIsValidScreenSize(int width, int height)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
if (width < rp->minWidth || rp->maxWidth < width)
|
||||
return 0;
|
||||
if (height < rp->minHeight || rp->maxHeight < height)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vncRandRResizeScreen(int width, int height)
|
||||
{
|
||||
ScreenPtr pScreen = screenInfo.screens[scrIdx];
|
||||
|
||||
/* Try to retain DPI when we resize */
|
||||
return RRScreenSizeSet(pScreen, width, height,
|
||||
pScreen->mmWidth * width / pScreen->width,
|
||||
pScreen->mmHeight * height / pScreen->height);
|
||||
}
|
||||
|
||||
void vncRandRUpdateSetTime(void)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
rp->lastSetTime = currentTime;
|
||||
}
|
||||
|
||||
int vncRandRHasOutputClones(void)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
for (int i = 0;i < rp->numCrtcs;i++) {
|
||||
if (rp->crtcs[i]->numOutputs > 1)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRGetOutputCount(void)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
return rp->numOutputs;
|
||||
}
|
||||
|
||||
int vncRandRGetAvailableOutputs(void)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
int availableOutputs;
|
||||
RRCrtcPtr *usedCrtcs;
|
||||
int numUsed;
|
||||
|
||||
int i, j, k;
|
||||
|
||||
usedCrtcs = malloc(sizeof(RRCrtcPtr) * rp->numCrtcs);
|
||||
if (usedCrtcs == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* This gets slightly complicated because we might need to hook a CRTC
|
||||
* up to the output, but also check that we don't try to use the same
|
||||
* CRTC for multiple outputs.
|
||||
*/
|
||||
availableOutputs = 0;
|
||||
numUsed = 0;
|
||||
for (i = 0;i < rp->numOutputs;i++) {
|
||||
RROutputPtr output;
|
||||
|
||||
output = rp->outputs[i];
|
||||
|
||||
if (output->crtc != NULL)
|
||||
availableOutputs++;
|
||||
else {
|
||||
for (j = 0;j < output->numCrtcs;j++) {
|
||||
if (output->crtcs[j]->numOutputs != 0)
|
||||
continue;
|
||||
|
||||
for (k = 0;k < numUsed;k++) {
|
||||
if (usedCrtcs[k] == output->crtcs[j])
|
||||
break;
|
||||
}
|
||||
if (k != numUsed)
|
||||
continue;
|
||||
|
||||
availableOutputs++;
|
||||
|
||||
usedCrtcs[numUsed] = output->crtcs[j];
|
||||
numUsed++;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(usedCrtcs);
|
||||
|
||||
return availableOutputs;
|
||||
}
|
||||
|
||||
char *vncRandRGetOutputName(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
return strdup(rp->outputs[outputIdx]->name);
|
||||
}
|
||||
|
||||
int vncRandRIsOutputEnabled(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
if (rp->outputs[outputIdx]->crtc == NULL)
|
||||
return 0;
|
||||
if (rp->outputs[outputIdx]->crtc->mode == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vncRandRIsOutputUsable(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
RROutputPtr output;
|
||||
int i;
|
||||
|
||||
output = rp->outputs[outputIdx];
|
||||
if (output->crtc != NULL)
|
||||
return 1;
|
||||
|
||||
/* Any unused CRTCs? */
|
||||
for (i = 0;i < output->numCrtcs;i++) {
|
||||
if (output->crtcs[i]->numOutputs == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRIsOutputConnected(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
RROutputPtr output;
|
||||
|
||||
output = rp->outputs[outputIdx];
|
||||
return (output->connection == RR_Connected);
|
||||
}
|
||||
|
||||
static RRModePtr vncRandRGetMatchingMode(int outputIdx, int width, int height)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
RROutputPtr output;
|
||||
|
||||
output = rp->outputs[outputIdx];
|
||||
|
||||
if (output->crtc != NULL) {
|
||||
unsigned int swap;
|
||||
switch (output->crtc->rotation) {
|
||||
case RR_Rotate_90:
|
||||
case RR_Rotate_270:
|
||||
swap = width;
|
||||
width = height;
|
||||
height = swap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < output->numModes; i++) {
|
||||
if ((output->modes[i]->mode.width == width) &&
|
||||
(output->modes[i]->mode.height == height))
|
||||
return output->modes[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vncRandRCheckOutputMode(int outputIdx, int width, int height)
|
||||
{
|
||||
if (vncRandRGetMatchingMode(outputIdx, width, height) != NULL)
|
||||
return 1;
|
||||
if (vncRandRCanCreateModes())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRDisableOutput(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
RRCrtcPtr crtc;
|
||||
int i;
|
||||
RROutputPtr *outputs;
|
||||
int numOutputs = 0;
|
||||
RRModePtr mode;
|
||||
int ret;
|
||||
|
||||
crtc = rp->outputs[outputIdx]->crtc;
|
||||
if (crtc == NULL)
|
||||
return 1;
|
||||
|
||||
/* Remove this output from the CRTC configuration */
|
||||
outputs = malloc(crtc->numOutputs * sizeof(RROutputPtr));
|
||||
if (!outputs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < crtc->numOutputs; i++) {
|
||||
if (rp->outputs[outputIdx] != crtc->outputs[i]) {
|
||||
outputs[numOutputs++] = crtc->outputs[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (numOutputs == 0) {
|
||||
mode = NULL;
|
||||
} else {
|
||||
mode = crtc->mode;
|
||||
}
|
||||
|
||||
ret = RRCrtcSet(crtc, mode, crtc->x, crtc->y, crtc->rotation, numOutputs, outputs);
|
||||
free(outputs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int vncRandRGetOutputId(int outputIdx)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
return rp->outputs[outputIdx]->id;
|
||||
}
|
||||
|
||||
int vncRandRGetOutputDimensions(int outputIdx,
|
||||
int *x, int *y, int *width, int *height)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
RRCrtcPtr crtc;
|
||||
int swap;
|
||||
*x = *y = *width = *height = 0;
|
||||
|
||||
crtc = rp->outputs[outputIdx]->crtc;
|
||||
if (crtc == NULL || !crtc->mode)
|
||||
return 1;
|
||||
|
||||
*x = crtc->x;
|
||||
*y = crtc->y;
|
||||
*width = crtc->mode->mode.width;
|
||||
*height = crtc->mode->mode.height;
|
||||
|
||||
switch (crtc->rotation & 0xf) {
|
||||
case RR_Rotate_90:
|
||||
case RR_Rotate_270:
|
||||
swap = *width;
|
||||
*width = *height;
|
||||
*height = swap;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRReconfigureOutput(int outputIdx, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
|
||||
|
||||
RROutputPtr output;
|
||||
RRCrtcPtr crtc;
|
||||
RRModePtr mode;
|
||||
|
||||
int i;
|
||||
|
||||
output = rp->outputs[outputIdx];
|
||||
crtc = output->crtc;
|
||||
|
||||
/* Need a CRTC? */
|
||||
if (crtc == NULL) {
|
||||
for (i = 0;i < output->numCrtcs;i++) {
|
||||
if (output->crtcs[i]->numOutputs != 0)
|
||||
continue;
|
||||
|
||||
crtc = output->crtcs[i];
|
||||
break;
|
||||
}
|
||||
|
||||
/* Couldn't find one... */
|
||||
if (crtc == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure we have the mode we want */
|
||||
mode = vncRandRGetMatchingMode(outputIdx, width, height);
|
||||
if (mode == NULL) {
|
||||
mode = vncRandRCreateMode(output, width, height);
|
||||
if (mode == NULL)
|
||||
return 0;
|
||||
}
|
||||
mode = vncRandRSetPreferredMode(output, mode);
|
||||
if (mode == NULL)
|
||||
return 0;
|
||||
|
||||
/* Reconfigure new mode and position */
|
||||
return RRCrtcSet(crtc, mode, x, y, crtc->rotation, 1, &output);
|
||||
}
|
||||
|
||||
int vncRandRCanCreateOutputs(int extraOutputs)
|
||||
{
|
||||
return vncRandRCanCreateScreenOutputs(scrIdx, extraOutputs);
|
||||
}
|
||||
|
||||
int vncRandRCreateOutputs(int extraOutputs)
|
||||
{
|
||||
return vncRandRCreateScreenOutputs(scrIdx, extraOutputs);
|
||||
}
|
||||
116
unix/xserver/hw/vnc/XorgGlue.c
Normal file
116
unix/xserver/hw/vnc/XorgGlue.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "scrnintstr.h"
|
||||
#ifdef RANDR
|
||||
#include "randrstr.h"
|
||||
#endif
|
||||
|
||||
#include "XorgGlue.h"
|
||||
|
||||
const char *vncGetDisplay(void)
|
||||
{
|
||||
return display;
|
||||
}
|
||||
|
||||
unsigned long vncGetServerGeneration(void)
|
||||
{
|
||||
return serverGeneration;
|
||||
}
|
||||
|
||||
void vncFatalError(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[4096];
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
va_end(args);
|
||||
|
||||
FatalError("%s", buffer);
|
||||
}
|
||||
|
||||
int vncGetScreenCount(void)
|
||||
{
|
||||
return screenInfo.numScreens;
|
||||
}
|
||||
|
||||
void vncGetScreenFormat(int scrIdx, int *depth, int *bpp,
|
||||
int *trueColour, int *bigEndian,
|
||||
int *redMask, int *greenMask, int *blueMask)
|
||||
{
|
||||
int i;
|
||||
VisualPtr vis = NULL;
|
||||
|
||||
assert(depth);
|
||||
assert(bpp);
|
||||
assert(trueColour);
|
||||
assert(bigEndian);
|
||||
assert(redMask);
|
||||
assert(greenMask);
|
||||
assert(blueMask);
|
||||
|
||||
*depth = screenInfo.screens[scrIdx]->rootDepth;
|
||||
|
||||
for (i = 0; i < screenInfo.numPixmapFormats; i++) {
|
||||
if (screenInfo.formats[i].depth == *depth) {
|
||||
*bpp = screenInfo.formats[i].bitsPerPixel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == screenInfo.numPixmapFormats)
|
||||
FatalError("No pixmap format for root depth\n");
|
||||
|
||||
*bigEndian = (screenInfo.imageByteOrder == MSBFirst);
|
||||
|
||||
for (i = 0; i < screenInfo.screens[scrIdx]->numVisuals; i++) {
|
||||
if (screenInfo.screens[scrIdx]->visuals[i].vid ==
|
||||
screenInfo.screens[scrIdx]->rootVisual) {
|
||||
vis = &screenInfo.screens[scrIdx]->visuals[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == screenInfo.screens[scrIdx]->numVisuals)
|
||||
FatalError("No visual record for root visual\n");
|
||||
|
||||
*trueColour = (vis->class == TrueColor);
|
||||
|
||||
*redMask = vis->redMask;
|
||||
*greenMask = vis->greenMask;
|
||||
*blueMask = vis->blueMask;
|
||||
}
|
||||
|
||||
int vncGetScreenX(int scrIdx)
|
||||
{
|
||||
return screenInfo.screens[scrIdx]->x;
|
||||
}
|
||||
|
||||
int vncGetScreenY(int scrIdx)
|
||||
{
|
||||
return screenInfo.screens[scrIdx]->y;
|
||||
}
|
||||
|
||||
61
unix/xserver/hw/vnc/XorgGlue.h
Normal file
61
unix/xserver/hw/vnc/XorgGlue.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef XORG_GLUE_H
|
||||
#define XORG_GLUE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define __printf_attr(a, b) __attribute__((__format__ (__printf__, a, b)))
|
||||
# define __noreturn_attr __attribute__((noreturn))
|
||||
#else
|
||||
# define __printf_attr(a, b)
|
||||
# define __noreturn_attr
|
||||
#endif // __GNUC__
|
||||
|
||||
const char *vncGetDisplay(void);
|
||||
unsigned long vncGetServerGeneration(void);
|
||||
|
||||
void vncFatalError(const char *format, ...) __printf_attr(1, 2) __noreturn_attr;
|
||||
|
||||
int vncGetScreenCount(void);
|
||||
|
||||
void vncGetScreenFormat(int scrIdx, int *depth, int *bpp,
|
||||
int *trueColour, int *bigEndian,
|
||||
int *redMask, int *greenMask, int *blueMask);
|
||||
|
||||
int vncGetScreenX(int scrIdx);
|
||||
int vncGetScreenY(int scrIdx);
|
||||
|
||||
// These hide in xvnc.c or vncModule.c
|
||||
void vncClientGone(int fd);
|
||||
int vncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs);
|
||||
int vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs);
|
||||
int vncRandRCanCreateModes(void);
|
||||
void* vncRandRCreateMode(void* output, int width, int height);
|
||||
void* vncRandRSetPreferredMode(void* output, void* mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
606
unix/xserver/hw/vnc/XserverDesktop.cc
Normal file
606
unix/xserver/hw/vnc/XserverDesktop.cc
Normal file
@@ -0,0 +1,606 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2009-2017 Pierre Ossman for Cendio AB
|
||||
* Copyright 2014 Brian P. Hinz
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// XserverDesktop.cxx
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <network/Socket.h>
|
||||
#include <rfb/Exception.h>
|
||||
#include <rfb/VNCServerST.h>
|
||||
#include <rfb/HTTPServer.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/ServerCore.h>
|
||||
|
||||
#include "XserverDesktop.h"
|
||||
#include "vncBlockHandler.h"
|
||||
#include "vncExtInit.h"
|
||||
#include "vncHooks.h"
|
||||
#include "vncSelection.h"
|
||||
#include "XorgGlue.h"
|
||||
#include "Input.h"
|
||||
|
||||
extern "C" {
|
||||
void vncSetGlueContext(int screenIndex);
|
||||
}
|
||||
|
||||
using namespace rfb;
|
||||
using namespace network;
|
||||
|
||||
static LogWriter vlog("XserverDesktop");
|
||||
|
||||
BoolParameter rawKeyboard("RawKeyboard",
|
||||
"Send keyboard events straight through and "
|
||||
"avoid mapping them to the current keyboard "
|
||||
"layout", false);
|
||||
IntParameter queryConnectTimeout("QueryConnectTimeout",
|
||||
"Number of seconds to show the "
|
||||
"Accept Connection dialog before "
|
||||
"rejecting the connection",
|
||||
10);
|
||||
|
||||
class FileHTTPServer : public rfb::HTTPServer {
|
||||
public:
|
||||
FileHTTPServer(XserverDesktop* d) : desktop(d) {}
|
||||
virtual ~FileHTTPServer() {}
|
||||
|
||||
virtual rdr::InStream* getFile(const char* name, const char** contentType,
|
||||
int* contentLength, time_t* lastModified)
|
||||
{
|
||||
if (name[0] != '/' || strstr(name, "..") != 0) {
|
||||
vlog.info("http request was for invalid file name");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(name, "/") == 0) name = "/index.vnc";
|
||||
|
||||
CharArray httpDirStr(httpDir.getData());
|
||||
CharArray fname(strlen(httpDirStr.buf)+strlen(name)+1);
|
||||
sprintf(fname.buf, "%s%s", httpDirStr.buf, name);
|
||||
int fd = open(fname.buf, O_RDONLY);
|
||||
if (fd < 0) return 0;
|
||||
rdr::InStream* is = new rdr::FdInStream(fd, -1, 0, true);
|
||||
*contentType = guessContentType(name, *contentType);
|
||||
if (strlen(name) > 4 && strcasecmp(&name[strlen(name)-4], ".vnc") == 0) {
|
||||
is = new rdr::SubstitutingInStream(is, desktop, 20);
|
||||
*contentType = "text/html";
|
||||
} else {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) == 0) {
|
||||
*contentLength = st.st_size;
|
||||
*lastModified = st.st_mtime;
|
||||
}
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
XserverDesktop* desktop;
|
||||
};
|
||||
|
||||
|
||||
XserverDesktop::XserverDesktop(int screenIndex_,
|
||||
std::list<network::SocketListener*> listeners_,
|
||||
std::list<network::SocketListener*> httpListeners_,
|
||||
const char* name, const rfb::PixelFormat &pf,
|
||||
int width, int height,
|
||||
void* fbptr, int stride)
|
||||
: screenIndex(screenIndex_),
|
||||
server(0), httpServer(0),
|
||||
listeners(listeners_), httpListeners(httpListeners_),
|
||||
directFbptr(true),
|
||||
queryConnectId(0), queryConnectTimer(this)
|
||||
{
|
||||
format = pf;
|
||||
|
||||
server = new VNCServerST(name, this);
|
||||
setFramebuffer(width, height, fbptr, stride);
|
||||
server->setQueryConnectionHandler(this);
|
||||
|
||||
if (!httpListeners.empty ())
|
||||
httpServer = new FileHTTPServer(this);
|
||||
|
||||
for (std::list<SocketListener*>::iterator i = listeners.begin();
|
||||
i != listeners.end();
|
||||
i++) {
|
||||
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
|
||||
}
|
||||
|
||||
for (std::list<SocketListener*>::iterator i = httpListeners.begin();
|
||||
i != httpListeners.end();
|
||||
i++) {
|
||||
vncSetNotifyFd((*i)->getFd(), screenIndex, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
XserverDesktop::~XserverDesktop()
|
||||
{
|
||||
while (!listeners.empty()) {
|
||||
vncRemoveNotifyFd(listeners.back()->getFd());
|
||||
delete listeners.back();
|
||||
listeners.pop_back();
|
||||
}
|
||||
while (!httpListeners.empty()) {
|
||||
vncRemoveNotifyFd(listeners.back()->getFd());
|
||||
delete httpListeners.back();
|
||||
httpListeners.pop_back();
|
||||
}
|
||||
if (!directFbptr)
|
||||
delete [] data;
|
||||
delete httpServer;
|
||||
delete server;
|
||||
}
|
||||
|
||||
void XserverDesktop::blockUpdates()
|
||||
{
|
||||
server->blockUpdates();
|
||||
}
|
||||
|
||||
void XserverDesktop::unblockUpdates()
|
||||
{
|
||||
server->unblockUpdates();
|
||||
}
|
||||
|
||||
void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_)
|
||||
{
|
||||
ScreenSet layout;
|
||||
|
||||
width_ = w;
|
||||
height_ = h;
|
||||
|
||||
if (!directFbptr) {
|
||||
delete [] data;
|
||||
directFbptr = true;
|
||||
}
|
||||
|
||||
if (!fbptr) {
|
||||
fbptr = new rdr::U8[w * h * (format.bpp/8)];
|
||||
stride_ = w;
|
||||
directFbptr = false;
|
||||
}
|
||||
|
||||
data = (rdr::U8*)fbptr;
|
||||
stride = stride_;
|
||||
|
||||
vncSetGlueContext(screenIndex);
|
||||
layout = ::computeScreenLayout(&outputIdMap);
|
||||
|
||||
server->setPixelBuffer(this, layout);
|
||||
}
|
||||
|
||||
void XserverDesktop::refreshScreenLayout()
|
||||
{
|
||||
vncSetGlueContext(screenIndex);
|
||||
server->setScreenLayout(::computeScreenLayout(&outputIdMap));
|
||||
}
|
||||
|
||||
char* XserverDesktop::substitute(const char* varName)
|
||||
{
|
||||
if (strcmp(varName, "$$") == 0) {
|
||||
return rfb::strDup("$");
|
||||
}
|
||||
if (strcmp(varName, "$PORT") == 0) {
|
||||
char* str = new char[10];
|
||||
sprintf(str, "%d", listeners.empty () ? 0 : (*listeners.begin ())->getMyPort());
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$WIDTH") == 0) {
|
||||
char* str = new char[10];
|
||||
sprintf(str, "%d", width());
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$HEIGHT") == 0) {
|
||||
char* str = new char[10];
|
||||
sprintf(str, "%d", height());
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$APPLETWIDTH") == 0) {
|
||||
char* str = new char[10];
|
||||
sprintf(str, "%d", width());
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$APPLETHEIGHT") == 0) {
|
||||
char* str = new char[10];
|
||||
sprintf(str, "%d", height());
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$DESKTOP") == 0) {
|
||||
return rfb::strDup(server->getName());
|
||||
}
|
||||
if (strcmp(varName, "$DISPLAY") == 0) {
|
||||
struct utsname uts;
|
||||
uname(&uts);
|
||||
char* str = new char[256];
|
||||
strncpy(str, uts.nodename, 240);
|
||||
str[239] = '\0'; /* Ensure string is zero-terminated */
|
||||
strcat(str, ":");
|
||||
strncat(str, vncGetDisplay(), 10);
|
||||
return str;
|
||||
}
|
||||
if (strcmp(varName, "$USER") == 0) {
|
||||
struct passwd* user = getpwuid(getuid());
|
||||
return rfb::strDup(user ? user->pw_name : "?");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rfb::VNCServerST::queryResult
|
||||
XserverDesktop::queryConnection(network::Socket* sock,
|
||||
const char* userName,
|
||||
char** reason)
|
||||
{
|
||||
int count;
|
||||
|
||||
if (queryConnectTimer.isStarted()) {
|
||||
*reason = strDup("Another connection is currently being queried.");
|
||||
return rfb::VNCServerST::REJECT;
|
||||
}
|
||||
|
||||
count = vncNotifyQueryConnect();
|
||||
if (count == 0) {
|
||||
*reason = strDup("Unable to query the local user to accept the connection.");
|
||||
return rfb::VNCServerST::REJECT;
|
||||
}
|
||||
|
||||
queryConnectAddress.replaceBuf(sock->getPeerAddress());
|
||||
if (!userName)
|
||||
userName = "(anonymous)";
|
||||
queryConnectUsername.replaceBuf(strDup(userName));
|
||||
queryConnectId = (uint32_t)(intptr_t)sock;
|
||||
queryConnectSocket = sock;
|
||||
|
||||
queryConnectTimer.start(queryConnectTimeout * 1000);
|
||||
|
||||
return rfb::VNCServerST::PENDING;
|
||||
}
|
||||
|
||||
void XserverDesktop::bell()
|
||||
{
|
||||
server->bell();
|
||||
}
|
||||
|
||||
void XserverDesktop::setLEDState(unsigned int state)
|
||||
{
|
||||
server->setLEDState(state);
|
||||
}
|
||||
|
||||
void XserverDesktop::serverCutText(const char* str, int len)
|
||||
{
|
||||
try {
|
||||
server->serverCutText(str, len);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::serverCutText: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::setDesktopName(const char* name)
|
||||
{
|
||||
try {
|
||||
server->setName(name);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::setDesktopName: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::setCursor(int width, int height, int hotX, int hotY,
|
||||
const unsigned char *rgbaData)
|
||||
{
|
||||
rdr::U8* cursorData;
|
||||
|
||||
rdr::U8 *out;
|
||||
const unsigned char *in;
|
||||
|
||||
cursorData = new rdr::U8[width * height * 4];
|
||||
|
||||
// Un-premultiply alpha
|
||||
in = rgbaData;
|
||||
out = cursorData;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
rdr::U8 alpha;
|
||||
|
||||
alpha = in[3];
|
||||
if (alpha == 0)
|
||||
alpha = 1; // Avoid division by zero
|
||||
|
||||
*out++ = (unsigned)*in++ * 255/alpha;
|
||||
*out++ = (unsigned)*in++ * 255/alpha;
|
||||
*out++ = (unsigned)*in++ * 255/alpha;
|
||||
*out++ = *in++;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
server->setCursor(width, height, Point(hotX, hotY), cursorData);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::setCursor: %s",e.str());
|
||||
}
|
||||
|
||||
delete [] cursorData;
|
||||
}
|
||||
|
||||
void XserverDesktop::add_changed(const rfb::Region ®ion)
|
||||
{
|
||||
try {
|
||||
server->add_changed(region);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::add_changed: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::add_copied(const rfb::Region &dest, const rfb::Point &delta)
|
||||
{
|
||||
try {
|
||||
server->add_copied(dest, delta);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::add_copied: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::handleSocketEvent(int fd, bool read, bool write)
|
||||
{
|
||||
try {
|
||||
if (read) {
|
||||
if (handleListenerEvent(fd, &listeners, server))
|
||||
return;
|
||||
if (handleListenerEvent(fd, &httpListeners, httpServer))
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleSocketEvent(fd, server, read, write))
|
||||
return;
|
||||
if (handleSocketEvent(fd, httpServer, read, write))
|
||||
return;
|
||||
|
||||
vlog.error("Cannot find file descriptor for socket event");
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::handleSocketEvent: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
bool XserverDesktop::handleListenerEvent(int fd,
|
||||
std::list<SocketListener*>* sockets,
|
||||
SocketServer* sockserv)
|
||||
{
|
||||
std::list<SocketListener*>::iterator i;
|
||||
|
||||
for (i = sockets->begin(); i != sockets->end(); i++) {
|
||||
if ((*i)->getFd() == fd)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sockets->end())
|
||||
return false;
|
||||
|
||||
Socket* sock = (*i)->accept();
|
||||
sock->outStream().setBlocking(false);
|
||||
vlog.debug("new client, sock %d", sock->getFd());
|
||||
sockserv->addSocket(sock);
|
||||
vncSetNotifyFd(sock->getFd(), screenIndex, true, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XserverDesktop::handleSocketEvent(int fd,
|
||||
SocketServer* sockserv,
|
||||
bool read, bool write)
|
||||
{
|
||||
std::list<Socket*> sockets;
|
||||
std::list<Socket*>::iterator i;
|
||||
|
||||
sockserv->getSockets(&sockets);
|
||||
for (i = sockets.begin(); i != sockets.end(); i++) {
|
||||
if ((*i)->getFd() == fd)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sockets.end())
|
||||
return false;
|
||||
|
||||
if (read)
|
||||
sockserv->processSocketReadEvent(*i);
|
||||
|
||||
if (write)
|
||||
sockserv->processSocketWriteEvent(*i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XserverDesktop::blockHandler(int* timeout)
|
||||
{
|
||||
// We don't have a good callback for when we can init input devices[1],
|
||||
// so we abuse the fact that this routine will be called first thing
|
||||
// once the dix is done initialising.
|
||||
// [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
|
||||
vncInitInputDevice();
|
||||
|
||||
try {
|
||||
std::list<Socket*> sockets;
|
||||
std::list<Socket*>::iterator i;
|
||||
server->getSockets(&sockets);
|
||||
for (i = sockets.begin(); i != sockets.end(); i++) {
|
||||
int fd = (*i)->getFd();
|
||||
if ((*i)->isShutdown()) {
|
||||
vlog.debug("client gone, sock %d",fd);
|
||||
vncRemoveNotifyFd(fd);
|
||||
server->removeSocket(*i);
|
||||
vncClientGone(fd);
|
||||
delete (*i);
|
||||
} else {
|
||||
/* Update existing NotifyFD to listen for write (or not) */
|
||||
vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0);
|
||||
}
|
||||
}
|
||||
if (httpServer) {
|
||||
httpServer->getSockets(&sockets);
|
||||
for (i = sockets.begin(); i != sockets.end(); i++) {
|
||||
int fd = (*i)->getFd();
|
||||
if ((*i)->isShutdown()) {
|
||||
vlog.debug("http client gone, sock %d",fd);
|
||||
vncRemoveNotifyFd(fd);
|
||||
httpServer->removeSocket(*i);
|
||||
delete (*i);
|
||||
} else {
|
||||
/* Update existing NotifyFD to listen for write (or not) */
|
||||
vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We are responsible for propagating mouse movement between clients
|
||||
int cursorX, cursorY;
|
||||
vncGetPointerPos(&cursorX, &cursorY);
|
||||
cursorX -= vncGetScreenX(screenIndex);
|
||||
cursorY -= vncGetScreenY(screenIndex);
|
||||
if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) {
|
||||
oldCursorPos.x = cursorX;
|
||||
oldCursorPos.y = cursorY;
|
||||
server->setCursorPos(oldCursorPos);
|
||||
}
|
||||
|
||||
// Trigger timers and check when the next will expire
|
||||
int nextTimeout = server->checkTimeouts();
|
||||
if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout))
|
||||
*timeout = nextTimeout;
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("XserverDesktop::blockHandler: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::addClient(Socket* sock, bool reverse)
|
||||
{
|
||||
vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse);
|
||||
sock->outStream().setBlocking(false);
|
||||
server->addSocket(sock, reverse);
|
||||
vncSetNotifyFd(sock->getFd(), screenIndex, true, false);
|
||||
}
|
||||
|
||||
void XserverDesktop::disconnectClients()
|
||||
{
|
||||
vlog.debug("disconnecting all clients");
|
||||
return server->closeClients("Disconnection from server end");
|
||||
}
|
||||
|
||||
|
||||
void XserverDesktop::getQueryConnect(uint32_t* opaqueId,
|
||||
const char** address,
|
||||
const char** username,
|
||||
int *timeout)
|
||||
{
|
||||
*opaqueId = queryConnectId;
|
||||
|
||||
if (!queryConnectTimer.isStarted()) {
|
||||
*address = "";
|
||||
*username = "";
|
||||
*timeout = 0;
|
||||
} else {
|
||||
*address = queryConnectAddress.buf;
|
||||
*username = queryConnectUsername.buf;
|
||||
*timeout = queryConnectTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::approveConnection(uint32_t opaqueId, bool accept,
|
||||
const char* rejectMsg)
|
||||
{
|
||||
if (queryConnectId == opaqueId) {
|
||||
server->approveConnection(queryConnectSocket, accept, rejectMsg);
|
||||
queryConnectId = 0;
|
||||
queryConnectTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SDesktop callbacks
|
||||
|
||||
|
||||
void XserverDesktop::pointerEvent(const Point& pos, int buttonMask)
|
||||
{
|
||||
vncPointerMove(pos.x + vncGetScreenX(screenIndex),
|
||||
pos.y + vncGetScreenY(screenIndex));
|
||||
vncPointerButtonAction(buttonMask);
|
||||
}
|
||||
|
||||
void XserverDesktop::clientCutText(const char* str, int len)
|
||||
{
|
||||
vncClientCutText(str, len);
|
||||
}
|
||||
|
||||
unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height,
|
||||
const rfb::ScreenSet& layout)
|
||||
{
|
||||
char buffer[2048];
|
||||
vlog.debug("Got request for framebuffer resize to %dx%d",
|
||||
fb_width, fb_height);
|
||||
layout.print(buffer, sizeof(buffer));
|
||||
vlog.debug("%s", buffer);
|
||||
|
||||
vncSetGlueContext(screenIndex);
|
||||
return ::setScreenLayout(fb_width, fb_height, layout, &outputIdMap);
|
||||
}
|
||||
|
||||
void XserverDesktop::grabRegion(const rfb::Region& region)
|
||||
{
|
||||
if (directFbptr)
|
||||
return;
|
||||
|
||||
std::vector<rfb::Rect> rects;
|
||||
std::vector<rfb::Rect>::iterator i;
|
||||
region.get_rects(&rects);
|
||||
for (i = rects.begin(); i != rects.end(); i++) {
|
||||
rdr::U8 *buffer;
|
||||
int stride;
|
||||
|
||||
buffer = getBufferRW(*i, &stride);
|
||||
vncGetScreenImage(screenIndex, i->tl.x, i->tl.y, i->width(), i->height(),
|
||||
(char*)buffer, stride * format.bpp/8);
|
||||
commitBufferRW(*i);
|
||||
}
|
||||
}
|
||||
|
||||
void XserverDesktop::keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
|
||||
{
|
||||
if (!rawKeyboard)
|
||||
keycode = 0;
|
||||
|
||||
vncKeyboardEvent(keysym, keycode, down);
|
||||
}
|
||||
|
||||
bool XserverDesktop::handleTimeout(Timer* t)
|
||||
{
|
||||
if (t == &queryConnectTimer) {
|
||||
server->approveConnection(queryConnectSocket, false,
|
||||
"The attempt to prompt the user to "
|
||||
"accept the connection failed");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
139
unix/xserver/hw/vnc/XserverDesktop.h
Normal file
139
unix/xserver/hw/vnc/XserverDesktop.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2009-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
//
|
||||
// XserverDesktop.h
|
||||
//
|
||||
|
||||
#ifndef __XSERVERDESKTOP_H__
|
||||
#define __XSERVERDESKTOP_H__
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <rfb/SDesktop.h>
|
||||
#include <rfb/HTTPServer.h>
|
||||
#include <rfb/PixelBuffer.h>
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/VNCServerST.h>
|
||||
#include <rdr/SubstitutingInStream.h>
|
||||
#include <unixcommon.h>
|
||||
#include "Input.h"
|
||||
|
||||
namespace rfb {
|
||||
class VNCServerST;
|
||||
}
|
||||
|
||||
namespace network { class SocketListener; class Socket; class SocketServer; }
|
||||
|
||||
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
|
||||
public rdr::Substitutor,
|
||||
public rfb::VNCServerST::QueryConnectionHandler,
|
||||
public rfb::Timer::Callback {
|
||||
public:
|
||||
|
||||
XserverDesktop(int screenIndex,
|
||||
std::list<network::SocketListener*> listeners_,
|
||||
std::list<network::SocketListener*> httpListeners_,
|
||||
const char* name, const rfb::PixelFormat &pf,
|
||||
int width, int height, void* fbptr, int stride);
|
||||
virtual ~XserverDesktop();
|
||||
|
||||
// methods called from X server code
|
||||
void blockUpdates();
|
||||
void unblockUpdates();
|
||||
void setFramebuffer(int w, int h, void* fbptr, int stride);
|
||||
void refreshScreenLayout();
|
||||
void bell();
|
||||
void setLEDState(unsigned int state);
|
||||
void serverCutText(const char* str, int len);
|
||||
void setDesktopName(const char* name);
|
||||
void setCursor(int width, int height, int hotX, int hotY,
|
||||
const unsigned char *rgbaData);
|
||||
void add_changed(const rfb::Region ®ion);
|
||||
void add_copied(const rfb::Region &dest, const rfb::Point &delta);
|
||||
void handleSocketEvent(int fd, bool read, bool write);
|
||||
void blockHandler(int* timeout);
|
||||
void addClient(network::Socket* sock, bool reverse);
|
||||
void disconnectClients();
|
||||
|
||||
// QueryConnect methods called from X server code
|
||||
// getQueryConnect()
|
||||
// Returns information about the currently waiting query
|
||||
// (or an id of 0 if there is none waiting)
|
||||
void getQueryConnect(uint32_t* opaqueId, const char** address,
|
||||
const char** username, int *timeout);
|
||||
|
||||
// approveConnection()
|
||||
// Used by X server code to supply the result of a query.
|
||||
void approveConnection(uint32_t opaqueId, bool accept,
|
||||
const char* rejectMsg=0);
|
||||
|
||||
// rfb::SDesktop callbacks
|
||||
virtual void pointerEvent(const rfb::Point& pos, int buttonMask);
|
||||
virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down);
|
||||
virtual void clientCutText(const char* str, int len);
|
||||
virtual unsigned int setScreenLayout(int fb_width, int fb_height,
|
||||
const rfb::ScreenSet& layout);
|
||||
|
||||
// rfb::PixelBuffer callbacks
|
||||
virtual void grabRegion(const rfb::Region& r);
|
||||
|
||||
// rdr::Substitutor callback
|
||||
virtual char* substitute(const char* varName);
|
||||
|
||||
// rfb::VNCServerST::QueryConnectionHandler callback
|
||||
virtual rfb::VNCServerST::queryResult queryConnection(network::Socket* sock,
|
||||
const char* userName,
|
||||
char** reason);
|
||||
|
||||
protected:
|
||||
bool handleListenerEvent(int fd,
|
||||
std::list<network::SocketListener*>* sockets,
|
||||
network::SocketServer* sockserv);
|
||||
bool handleSocketEvent(int fd,
|
||||
network::SocketServer* sockserv,
|
||||
bool read, bool write);
|
||||
|
||||
virtual bool handleTimeout(rfb::Timer* t);
|
||||
|
||||
private:
|
||||
|
||||
int screenIndex;
|
||||
rfb::VNCServerST* server;
|
||||
rfb::HTTPServer* httpServer;
|
||||
std::list<network::SocketListener*> listeners;
|
||||
std::list<network::SocketListener*> httpListeners;
|
||||
bool directFbptr;
|
||||
|
||||
uint32_t queryConnectId;
|
||||
network::Socket* queryConnectSocket;
|
||||
rfb::CharArray queryConnectAddress;
|
||||
rfb::CharArray queryConnectUsername;
|
||||
rfb::Timer queryConnectTimer;
|
||||
|
||||
OutputIdMap outputIdMap;
|
||||
|
||||
rfb::Point oldCursorPos;
|
||||
};
|
||||
#endif
|
||||
524
unix/xserver/hw/vnc/Xvnc.man
Normal file
524
unix/xserver/hw/vnc/Xvnc.man
Normal file
@@ -0,0 +1,524 @@
|
||||
.TH Xvnc 1 "" "KasmVNC" "Virtual Network Computing"
|
||||
.SH NAME
|
||||
Xvnc \- the X VNC server
|
||||
.SH SYNOPSIS
|
||||
.B Xvnc
|
||||
.RI [ options ]
|
||||
.RI : display#
|
||||
.SH DESCRIPTION
|
||||
.B Xvnc
|
||||
is the X VNC (Virtual Network Computing) server. It is based on a standard X
|
||||
server, but it has a "virtual" screen rather than a physical one. X
|
||||
applications display themselves on it as if it were a normal X display, but
|
||||
they can only be accessed via a VNC viewer - see \fBvncviewer\fP(1).
|
||||
|
||||
So Xvnc is really two servers in one. To the applications it is an X server,
|
||||
and to the remote VNC users it is a VNC server. By convention we have arranged
|
||||
that the VNC server display number will be the same as the X server display
|
||||
number, which means you can use eg. snoopy:2 to refer to display 2 on machine
|
||||
"snoopy" in both the X world and the VNC world.
|
||||
|
||||
The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This
|
||||
sets up the environment appropriately and runs some X applications to get you
|
||||
going. See the manual page for \fBvncserver\fP(1) for more information.
|
||||
|
||||
.SH OPTIONS
|
||||
.B Xvnc
|
||||
takes lots of options - running \fBXvnc -help\fP gives a list. Many of these
|
||||
are standard X server options, which are described in the \fBXserver\fP(1)
|
||||
manual page. In addition to options which can only be set via the
|
||||
command-line, there are also "parameters" which can be set both via the
|
||||
command-line and through the \fBvncconfig\fP(1) program.
|
||||
|
||||
.TP
|
||||
.B \-geometry \fIwidth\fPx\fIheight\fP
|
||||
Specify the size of the desktop to be created. Default is 1024x768.
|
||||
.
|
||||
.TP
|
||||
.B \-depth \fIdepth\fP
|
||||
Specify the pixel depth in bits of the desktop to be created. Default is 24,
|
||||
other possible values are 8, 15, and 16 - anything else is likely to cause
|
||||
strange behaviour by applications.
|
||||
.
|
||||
.TP
|
||||
.B \-pixelformat \fIformat\fP
|
||||
Specify pixel format for server to use (BGRnnn or RGBnnn). The default for
|
||||
depth 8 is BGR233 (meaning the most significant two bits represent blue, the
|
||||
next three green, and the least significant three represent red), the default
|
||||
for depth 16 is RGB565 and for depth 24 is RGB888.
|
||||
.
|
||||
.TP
|
||||
.B \-interface \fIIP address\fP
|
||||
Listen on interface. By default Xvnc listens on all available interfaces.
|
||||
.
|
||||
.TP
|
||||
.B \-inetd
|
||||
This significantly changes Xvnc's behaviour so that it can be launched from
|
||||
inetd. See the section below on usage with inetd.
|
||||
.
|
||||
.TP
|
||||
.B \-help
|
||||
List all the options and parameters
|
||||
|
||||
.SH PARAMETERS
|
||||
VNC parameters can be set both via the command-line and through the
|
||||
\fBvncconfig\fP(1) program, and with a VNC-enabled Xorg server via Options
|
||||
entries in the xorg.conf file.
|
||||
|
||||
Parameters can be turned on with -\fIparam\fP or off with
|
||||
-\fIparam\fP=0. Parameters which take a value can be specified as
|
||||
-\fIparam\fP \fIvalue\fP. Other valid forms are \fIparam\fP\fB=\fP\fIvalue\fP
|
||||
-\fIparam\fP=\fIvalue\fP --\fIparam\fP=\fIvalue\fP. Parameter names are
|
||||
case-insensitive.
|
||||
|
||||
.TP
|
||||
.B \-desktop \fIdesktop-name\fP
|
||||
Each desktop has a name which may be displayed by the viewer. It defaults to
|
||||
"x11".
|
||||
.
|
||||
.TP
|
||||
.B \-rfbport \fIport\fP
|
||||
Specifies the TCP port on which Xvnc listens for connections from viewers (the
|
||||
protocol used in VNC is called RFB - "remote framebuffer"). The default is
|
||||
5900 plus the display number.
|
||||
.
|
||||
.TP
|
||||
.B \-UseIPv4
|
||||
Use IPv4 for incoming and outgoing connections. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-UseIPv6
|
||||
Use IPv6 for incoming and outgoing connections. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-rfbunixpath \fIpath\fP
|
||||
Specifies the path of a Unix domain socket on which Xvnc listens for
|
||||
connections from viewers, instead of listening on a TCP port.
|
||||
.
|
||||
.TP
|
||||
.B \-rfbunixmode \fImode\fP
|
||||
Specifies the mode of the Unix domain socket. The default is 0600.
|
||||
.
|
||||
.TP
|
||||
.B \-rfbwait \fItime\fP, \-ClientWaitTimeMillis \fItime\fP
|
||||
Time in milliseconds to wait for a viewer which is blocking the server. This is
|
||||
necessary because the server is single-threaded and sometimes blocks until the
|
||||
viewer has finished sending or receiving a message - note that this does not
|
||||
mean an update will be aborted after this time. Default is 20000 (20 seconds).
|
||||
.
|
||||
.TP
|
||||
.B \-httpd \fIdirectory\fP
|
||||
Run a mini-HTTP server which serves files from the given directory. Normally
|
||||
the directory will contain the kasmweb client. It will use the websocket port.
|
||||
.
|
||||
.TP
|
||||
.B \-rfbauth \fIpasswd-file\fP, \-PasswordFile \fIpasswd-file\fP
|
||||
Password file for VNC authentication. There is no default, you should
|
||||
specify the password file explicitly. Password file should be created with
|
||||
the \fBvncpasswd\fP(1) utility. The file is accessed each time a connection
|
||||
comes in, so it can be changed on the fly.
|
||||
.
|
||||
.TP
|
||||
.B \-AcceptCutText
|
||||
Accept clipboard updates from clients. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-MaxCutText \fIbytes\fP
|
||||
The maximum size of a clipboard update that will be accepted from a client.
|
||||
Default is \fB262144\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-SendCutText
|
||||
Send clipboard changes to clients. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-SendPrimary
|
||||
Send the primary selection and cut buffer to the server as well as the
|
||||
clipboard selection. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-AcceptPointerEvents
|
||||
Accept pointer press and release events from clients. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-AcceptKeyEvents
|
||||
Accept key press and release events from clients. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-AcceptSetDesktopSize
|
||||
Accept requests to resize the size of the desktop. Default is on.
|
||||
.
|
||||
.TP
|
||||
.B \-DisconnectClients
|
||||
Disconnect existing clients if an incoming connection is non-shared. Default is
|
||||
on. If \fBDisconnectClients\fP is false, then a new non-shared connection will
|
||||
be refused while there is a client active. When combined with
|
||||
\fBNeverShared\fP this means only one client is allowed at a time.
|
||||
.
|
||||
.TP
|
||||
.B \-NeverShared
|
||||
Never treat incoming connections as shared, regardless of the client-specified
|
||||
setting. Default is off.
|
||||
.
|
||||
.TP
|
||||
.B \-AlwaysShared
|
||||
Always treat incoming connections as shared, regardless of the client-specified
|
||||
setting. Default is off.
|
||||
.
|
||||
.TP
|
||||
.B \-Protocol3.3
|
||||
Always use protocol version 3.3 for backwards compatibility with badly-behaved
|
||||
clients. Default is off.
|
||||
.
|
||||
.TP
|
||||
.B \-FrameRate \fIfps\fP
|
||||
The maximum number of updates per second sent to each client. If the screen
|
||||
updates any faster then those changes will be aggregated and sent in a single
|
||||
update to the client. Note that this only controls the maximum rate and a
|
||||
client may get a lower rate when resources are limited. Default is \fB60\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-DynamicQualityMin \fImin\fP
|
||||
The minimum quality to with dynamic JPEG quality scaling. The accepted values
|
||||
are 0-9 where 0 is low and 9 is high, with the same meaning as the client-side
|
||||
-quality parameter. Default is \fB7\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-DynamicQualityMax \fImax\fP
|
||||
The maximum quality to use with dynamic JPEG quality scaling. Setting this to
|
||||
zero disables dynamic JPEG quality scaling. The accepted values are 0-9 where 0
|
||||
is low and 9 is high, with the same meaning as the client-side -quality parameter.
|
||||
Default is \fB8\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-TreatLossless \fIquality\fP
|
||||
Treat lossy quality levels above and including this as lossless, without
|
||||
sending lossless updates for them. 0-9, 10 disables this.
|
||||
Default is \fB10\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-PreferBandwidth
|
||||
Prefer bandwidth over quality, and set various options for lower bandwidth use.
|
||||
The default is off, aka to prefer quality. You can override individual values
|
||||
by setting them after this switch on the command line. This switch sets the
|
||||
following:
|
||||
.br
|
||||
- dynamic JPEG quality range 2-9
|
||||
.br
|
||||
- TreatLossless 8
|
||||
.
|
||||
.TP
|
||||
.B \-RectThreads \fInum\fP
|
||||
Use this many threads to compress rects in parallel. Default \fB0\fP (automatic),
|
||||
set to \fB1\fP to disable.
|
||||
.
|
||||
.TP
|
||||
.B \-JpegVideoQuality \fInum\fP
|
||||
The JPEG quality to use when in video mode.
|
||||
Default \fB-1\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-WebpVideoQuality \fInum\fP
|
||||
The WEBP quality to use when in video mode.
|
||||
Default \fB-1\fP.
|
||||
.B \-MaxVideoResolution \fI1920x1080\fP
|
||||
When in video mode, downscale the screen to max this size. Keeps aspect ratio.
|
||||
Default \fB1920x1080\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-VideoTime \fIseconds\fP
|
||||
High rate of change must happen for this many seconds to switch to video mode.
|
||||
Default \fB5\fP, set \fB0\fP to always enable.
|
||||
.
|
||||
.TP
|
||||
.B \-VideoOutTime \fIseconds\fP
|
||||
The rate of change must be below the VideoArea threshold for this many seconds
|
||||
to switch out of video mode.
|
||||
Default \fB3\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-VideoArea \fIpercentage\fP
|
||||
High rate of change must happen for this % of the screen to switch to video mode.
|
||||
Default \fB45\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-PrintVideoArea
|
||||
Print the detected video area % value.
|
||||
Default off.
|
||||
.
|
||||
.TP
|
||||
.B \-VideoScaling \fItype\fP
|
||||
Scaling method to use when in downscaled video mode. 0 = nearest, 1 = bilinear,
|
||||
2 = progressive bilinear.
|
||||
Default \fB2\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-CompareFB \fImode\fP
|
||||
Perform pixel comparison on framebuffer to reduce unnecessary updates. Can
|
||||
be either \fB0\fP (off), \fB1\fP (always) or \fB2\fP (auto). Default is
|
||||
\fB2\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-ZlibLevel \fIlevel\fP
|
||||
Zlib compression level for ZRLE encoding (it does not affect Tight encoding).
|
||||
Acceptable values are between 0 and 9. Default is to use the standard
|
||||
compression level provided by the \fBzlib\fP(3) compression library.
|
||||
.
|
||||
.TP
|
||||
.B \-ImprovedHextile
|
||||
Use improved compression algorithm for Hextile encoding which achieves better
|
||||
compression ratios by the cost of using slightly more CPU time. Default is
|
||||
on.
|
||||
.
|
||||
.TP
|
||||
.B \-IgnoreClientSettingsKasm
|
||||
Ignore the additional client settings exposed in Kasm. Default off.
|
||||
Kasm exposes a few settings to the client the standard VNC does not.
|
||||
This param lets the server ignore those.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipSendMax \fIbytes\fP
|
||||
Limit clipboard bytes to send to clients in one transaction. Default 10,000.
|
||||
0 disables the limit, use \fBSendCutText\fP to disable clipboard sending entirely.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipAcceptMax \fIbytes\fP
|
||||
Limit clipboard bytes to receive from clients in one transaction. Default 10,000.
|
||||
0 disables the limit, use \fBAcceptCutText\fP to disable clipboard receiving entirely.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_ClipDelay \fIms\fP
|
||||
This many milliseconds must pass between clipboard actions. Default 1000.
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_KeyRateLimit \fIkeys-per-second\fP
|
||||
Reject keyboard presses over this many per second. Default 0 (disabled).
|
||||
.
|
||||
.TP
|
||||
.B \-DLP_Log \fIoff/info/verbose\fP
|
||||
Log clipboard and keyboard actions. Info logs just clipboard direction and size,
|
||||
verbose adds the contents for both.
|
||||
.
|
||||
.TP
|
||||
.B \-noWebsocket
|
||||
Disable websockets and expose a traditional VNC port (5901, etc.).
|
||||
.
|
||||
.TP
|
||||
.B \-websocketPort \fIport\fP
|
||||
Listen for websocket connections on this port, default 6800.
|
||||
.
|
||||
.TP
|
||||
.B \-cert \fIpath\fP
|
||||
SSL pem cert to use for websocket connections, default empty/not used.
|
||||
.
|
||||
.TP
|
||||
.B \-sslOnly
|
||||
Require SSL for websocket connections. Default off, non-SSL allowed.
|
||||
.
|
||||
.TP
|
||||
.B \-basicAuth \fIuser:pass\fP
|
||||
Username and password for websocket connections. Default empty, no authentication required.
|
||||
.
|
||||
.TP
|
||||
.B \-SecurityTypes \fIsec-types\fP
|
||||
Specify which security scheme to use for incoming connections. Valid values
|
||||
are a comma separated list of \fBNone\fP, \fBVncAuth\fP, \fBPlain\fP,
|
||||
\fBTLSNone\fP, \fBTLSVnc\fP, \fBTLSPlain\fP, \fBX509None\fP, \fBX509Vnc\fP
|
||||
and \fBX509Plain\fP. Default is \fBVncAuth,TLSVnc\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-Password \fIpassword\fP
|
||||
Obfuscated binary encoding of the password which clients must supply to
|
||||
access the server. Using this parameter is insecure, use \fBPasswordFile\fP
|
||||
parameter instead.
|
||||
.
|
||||
.TP
|
||||
.B \-PlainUsers \fIuser-list\fP
|
||||
A comma separated list of user names that are allowed to authenticate via
|
||||
any of the "Plain" security types (Plain, TLSPlain, etc.). Specify \fB*\fP
|
||||
to allow any user to authenticate using this security type. Default is to
|
||||
deny all users.
|
||||
.
|
||||
.TP
|
||||
.B \-pam_service \fIname\fP, \-PAMService \fIname\fP
|
||||
PAM service name to use when authentication users using any of the "Plain"
|
||||
security types. Default is \fBvnc\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-X509Cert \fIpath\fP
|
||||
Path to a X509 certificate in PEM format to be used for all X509 based
|
||||
security types (X509None, X509Vnc, etc.).
|
||||
.
|
||||
.TP
|
||||
.B \-X509Key \fIpath\fP
|
||||
Private key counter part to the certificate given in \fBX509Cert\fP. Must
|
||||
also be in PEM format.
|
||||
.
|
||||
.TP
|
||||
.B \-GnuTLSPriority \fIpriority\fP
|
||||
GnuTLS priority string that controls the TLS session’s handshake algorithms.
|
||||
See the GnuTLS manual for possible values. Default is \fBNORMAL\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-BlacklistThreshold \fIcount\fP
|
||||
The number of unauthenticated connection attempts allowed from any individual
|
||||
host before that host is black-listed. Default is 5.
|
||||
.
|
||||
.TP
|
||||
.B \-BlacklistTimeout \fIseconds\fP
|
||||
The initial timeout applied when a host is first black-listed. The host
|
||||
cannot re-attempt a connection until the timeout expires. Default is 10.
|
||||
.
|
||||
.TP
|
||||
.B \-IdleTimeout \fIseconds\fP
|
||||
The number of seconds after which an idle VNC connection will be dropped.
|
||||
Default is 0, which means that idle connections will never be dropped.
|
||||
.
|
||||
.TP
|
||||
.B \-MaxDisconnectionTime \fIseconds\fP
|
||||
Terminate when no client has been connected for \fIN\fP seconds. Default is
|
||||
0.
|
||||
.
|
||||
.TP
|
||||
.B \-MaxConnectionTime \fIseconds\fP
|
||||
Terminate when a client has been connected for \fIN\fP seconds. Default is
|
||||
0.
|
||||
.
|
||||
.TP
|
||||
.B \-MaxIdleTime \fIseconds\fP
|
||||
Terminate after \fIN\fP seconds of user inactivity. Default is 0.
|
||||
.
|
||||
.TP
|
||||
.B \-QueryConnect
|
||||
Prompts the user of the desktop to explicitly accept or reject incoming
|
||||
connections. Default is off.
|
||||
|
||||
The \fBvncconfig\fP(1) program must be running on the desktop in order for
|
||||
QueryConnect to be supported.
|
||||
.
|
||||
.TP
|
||||
.B \-QueryConnectTimeout \fIseconds\fP
|
||||
Number of seconds to show the Accept Connection dialog before rejecting the
|
||||
connection. Default is \fB10\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-localhost
|
||||
Only allow connections from the same machine. Useful if you use SSH and want to
|
||||
stop non-SSH connections from any other hosts.
|
||||
.
|
||||
.TP
|
||||
.B \-Log \fIlogname\fP:\fIdest\fP:\fIlevel\fP
|
||||
Configures the debug log settings. \fIdest\fP can currently be \fBstderr\fP,
|
||||
\fBstdout\fP or \fBsyslog\fP, and \fIlevel\fP is between 0 and 100, 100 meaning
|
||||
most verbose output. \fIlogname\fP is usually \fB*\fP meaning all, but you can
|
||||
target a specific source file if you know the name of its "LogWriter". Default
|
||||
is \fB*:stderr:30\fP.
|
||||
.
|
||||
.TP
|
||||
.B \-RemapKeys \fImapping
|
||||
Sets up a keyboard mapping.
|
||||
.I mapping
|
||||
is a comma-separated string of character mappings, each of the form
|
||||
.IR char -> char ,
|
||||
or
|
||||
.IR char <> char ,
|
||||
where
|
||||
.I char
|
||||
is a hexadecimal keysym. For example, to exchange the " and @ symbols you would specify the following:
|
||||
|
||||
.RS 10
|
||||
RemapKeys=0x22<>0x40
|
||||
.RE
|
||||
.
|
||||
.TP
|
||||
.B \-AvoidShiftNumLock
|
||||
Key affected by NumLock often require a fake Shift to be inserted in order
|
||||
for the correct symbol to be generated. Turning on this option avoids these
|
||||
extra fake Shift events but may result in a slightly different symbol
|
||||
(e.g. a Return instead of a keypad Enter).
|
||||
.
|
||||
.TP
|
||||
.B \-RawKeyboard
|
||||
Send keyboard events straight through and avoid mapping them to the current
|
||||
keyboard layout. This effectively makes the keyboard behave according to the
|
||||
layout configured on the server instead of the layout configured on the
|
||||
client. Default is off.
|
||||
.
|
||||
.TP
|
||||
.B \-AllowOverride
|
||||
Comma separated list of parameters that can be modified using VNC extension.
|
||||
Parameters can be modified for example using \fBvncconfig\fP(1) program from
|
||||
inside a running session.
|
||||
|
||||
Allowing override of parameters such as \fBPAMService\fP or \fBPasswordFile\fP
|
||||
can negatively impact security if Xvnc runs under different user than the
|
||||
programs allowed to override the parameters.
|
||||
|
||||
When \fBNoClipboard\fP parameter is set, allowing override of \fBSendCutText\fP
|
||||
and \fBAcceptCutText\fP has no effect.
|
||||
|
||||
Default is \fBdesktop,AcceptPointerEvents,SendCutText,AcceptCutText,SendPrimary,SetPrimary\fP.
|
||||
|
||||
.SH USAGE WITH INETD
|
||||
By configuring the \fBinetd\fP(1) service appropriately, Xvnc can be launched
|
||||
on demand when a connection comes in, rather than having to be started
|
||||
manually. When given the \fB-inetd\fP option, instead of listening for TCP
|
||||
connections on a given port it uses its standard input and standard output.
|
||||
There are two modes controlled by the wait/nowait entry in the inetd.conf file.
|
||||
|
||||
In the nowait mode, Xvnc uses its standard input and output directly as the
|
||||
connection to a viewer. It never has a listening socket, so cannot accept
|
||||
further connections from viewers (it can however connect out to listening
|
||||
viewers by use of the vncconfig program). Further viewer connections to the
|
||||
same TCP port result in inetd spawning off a new Xvnc to deal with each
|
||||
connection. When the connection to the viewer dies, the Xvnc and any
|
||||
associated X clients die. This behaviour is most useful when combined with the
|
||||
XDMCP options -query and -once. An typical example in inetd.conf might be (all
|
||||
on one line):
|
||||
|
||||
5950 stream tcp nowait nobody /usr/local/bin/Xvnc Xvnc -inetd -query
|
||||
localhost -once securitytypes=none
|
||||
|
||||
In this example a viewer connection to :50 will result in a new Xvnc for that
|
||||
connection which should display the standard XDM login screen on that machine.
|
||||
Because the user needs to login via XDM, it is usually OK to accept connections
|
||||
without a VNC password in this case.
|
||||
|
||||
In the wait mode, when the first connection comes in, inetd gives the listening
|
||||
socket to Xvnc. This means that for a given TCP port, there is only ever one
|
||||
Xvnc at a time. Further viewer connections to the same port are accepted by
|
||||
the same Xvnc in the normal way. Even when the original connection is broken,
|
||||
the Xvnc will continue to run. If this is used with the XDMCP options -query
|
||||
and -once, the Xvnc and associated X clients will die when the user logs out of
|
||||
the X session in the normal way. It is important to use a VNC password in this
|
||||
case. A typical entry in inetd.conf might be:
|
||||
|
||||
5951 stream tcp wait james /usr/local/bin/Xvnc Xvnc -inetd -query localhost -once passwordFile=/home/james/.vnc/passwd
|
||||
|
||||
In fact typically, you would have one entry for each user who uses VNC
|
||||
regularly, each of whom has their own dedicated TCP port which they use. In
|
||||
this example, when user "james" connects to :51, he enters his VNC password,
|
||||
then gets the XDM login screen where he logs in in the normal way. However,
|
||||
unlike the previous example, if he disconnects, the session remains persistent,
|
||||
and when he reconnects he will get the same session back again. When he logs
|
||||
out of the X session, the Xvnc will die, but of course a new one will be
|
||||
created automatically the next time he connects.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR vncconfig (1),
|
||||
.BR vncpasswd (1),
|
||||
.BR vncserver (1),
|
||||
.BR vncviewer (1),
|
||||
.BR Xserver (1),
|
||||
.BR inetd (1)
|
||||
.br
|
||||
http://kasmweb.com
|
||||
|
||||
.SH AUTHOR
|
||||
Tristan Richardson, RealVNC Ltd. and others.
|
||||
|
||||
VNC was originally developed by the RealVNC team while at Olivetti
|
||||
Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
|
||||
implemented by Constantin Kaplinsky. Many other people have since
|
||||
participated in development, testing and support. This manual is part
|
||||
of the KasmVNC software suite.
|
||||
18
unix/xserver/hw/vnc/buildtime.c
Normal file
18
unix/xserver/hw/vnc/buildtime.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
char buildtime[] = __DATE__ " " __TIME__;
|
||||
245
unix/xserver/hw/vnc/qnum_to_xorgevdev.c
Normal file
245
unix/xserver/hw/vnc/qnum_to_xorgevdev.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* This file is auto-generated from keymaps.csv on 2017-08-28 13:03
|
||||
* Database checksum sha256(f8aeff0c3430077a350e3d7ba2b335b381bd929ac4b193413730a402ff3f0097)
|
||||
* To re-generate, run:
|
||||
* keymap-gen --lang=stdc code-map keymaps.csv qnum xorgevdev
|
||||
*/
|
||||
const unsigned short code_map_qnum_to_xorgevdev[254] = {
|
||||
[0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgevdev:9 */
|
||||
[0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgevdev:10 */
|
||||
[0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgevdev:11 */
|
||||
[0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgevdev:12 */
|
||||
[0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgevdev:13 */
|
||||
[0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgevdev:14 */
|
||||
[0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgevdev:15 */
|
||||
[0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgevdev:16 */
|
||||
[0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgevdev:17 */
|
||||
[0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgevdev:18 */
|
||||
[0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgevdev:19 */
|
||||
[0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgevdev:20 */
|
||||
[0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgevdev:21 */
|
||||
[0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgevdev:22 */
|
||||
[0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgevdev:23 */
|
||||
[0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgevdev:24 */
|
||||
[0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgevdev:25 */
|
||||
[0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgevdev:26 */
|
||||
[0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgevdev:27 */
|
||||
[0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgevdev:28 */
|
||||
[0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgevdev:29 */
|
||||
[0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgevdev:30 */
|
||||
[0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgevdev:31 */
|
||||
[0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgevdev:32 */
|
||||
[0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgevdev:33 */
|
||||
[0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgevdev:34 */
|
||||
[0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgevdev:35 */
|
||||
[0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgevdev:36 */
|
||||
[0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgevdev:37 */
|
||||
[0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgevdev:38 */
|
||||
[0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgevdev:39 */
|
||||
[0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgevdev:40 */
|
||||
[0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgevdev:41 */
|
||||
[0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgevdev:42 */
|
||||
[0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgevdev:43 */
|
||||
[0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgevdev:44 */
|
||||
[0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgevdev:45 */
|
||||
[0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgevdev:46 */
|
||||
[0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgevdev:47 */
|
||||
[0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgevdev:48 */
|
||||
[0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgevdev:49 */
|
||||
[0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgevdev:50 */
|
||||
[0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgevdev:51 */
|
||||
[0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgevdev:52 */
|
||||
[0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgevdev:53 */
|
||||
[0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgevdev:54 */
|
||||
[0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgevdev:55 */
|
||||
[0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgevdev:56 */
|
||||
[0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgevdev:57 */
|
||||
[0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgevdev:58 */
|
||||
[0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgevdev:59 */
|
||||
[0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgevdev:60 */
|
||||
[0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgevdev:61 */
|
||||
[0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgevdev:62 */
|
||||
[0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgevdev:63 */
|
||||
[0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgevdev:64 */
|
||||
[0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgevdev:65 */
|
||||
[0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgevdev:66 */
|
||||
[0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgevdev:67 */
|
||||
[0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgevdev:68 */
|
||||
[0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgevdev:69 */
|
||||
[0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgevdev:70 */
|
||||
[0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgevdev:71 */
|
||||
[0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgevdev:72 */
|
||||
[0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgevdev:73 */
|
||||
[0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgevdev:74 */
|
||||
[0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgevdev:75 */
|
||||
[0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgevdev:76 */
|
||||
[0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgevdev:77 */
|
||||
[0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgevdev:78 */
|
||||
[0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgevdev:79 */
|
||||
[0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgevdev:80 */
|
||||
[0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgevdev:81 */
|
||||
[0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgevdev:82 */
|
||||
[0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgevdev:83 */
|
||||
[0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgevdev:84 */
|
||||
[0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgevdev:85 */
|
||||
[0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgevdev:86 */
|
||||
[0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgevdev:87 */
|
||||
[0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgevdev:88 */
|
||||
[0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgevdev:89 */
|
||||
[0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgevdev:90 */
|
||||
[0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgevdev:91 */
|
||||
[0x54] = 0x6b, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */
|
||||
[0x55] = 0xc2, /* qnum:85 -> linux:186 (KEY_F16) -> xorgevdev:194 */
|
||||
[0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgevdev:94 */
|
||||
[0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgevdev:95 */
|
||||
[0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgevdev:96 */
|
||||
[0x59] = 0x7d, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgevdev:125 */
|
||||
[0x5a] = 0xc6, /* qnum:90 -> linux:190 (KEY_F20) -> xorgevdev:198 */
|
||||
[0x5b] = 0x6d, /* qnum:91 -> linux:101 (KEY_LINEFEED) -> xorgevdev:109 */
|
||||
[0x5c] = 0x67, /* qnum:92 -> linux:95 (KEY_KPJPCOMMA) -> xorgevdev:103 */
|
||||
[0x5d] = 0xbf, /* qnum:93 -> linux:183 (KEY_F13) -> xorgevdev:191 */
|
||||
[0x5e] = 0xc0, /* qnum:94 -> linux:184 (KEY_F14) -> xorgevdev:192 */
|
||||
[0x5f] = 0xc1, /* qnum:95 -> linux:185 (KEY_F15) -> xorgevdev:193 */
|
||||
[0x63] = 0xb1, /* qnum:99 -> linux:169 (KEY_PHONE) -> xorgevdev:177 */
|
||||
[0x64] = 0x8e, /* qnum:100 -> linux:134 (KEY_OPEN) -> xorgevdev:142 */
|
||||
[0x65] = 0x8f, /* qnum:101 -> linux:135 (KEY_PASTE) -> xorgevdev:143 */
|
||||
[0x66] = 0x95, /* qnum:102 -> linux:141 (KEY_SETUP) -> xorgevdev:149 */
|
||||
[0x67] = 0x98, /* qnum:103 -> linux:144 (KEY_FILE) -> xorgevdev:152 */
|
||||
[0x68] = 0x99, /* qnum:104 -> linux:145 (KEY_SENDFILE) -> xorgevdev:153 */
|
||||
[0x69] = 0x9a, /* qnum:105 -> linux:146 (KEY_DELETEFILE) -> xorgevdev:154 */
|
||||
[0x6a] = 0x9f, /* qnum:106 -> linux:151 (KEY_MSDOS) -> xorgevdev:159 */
|
||||
[0x6b] = 0xa1, /* qnum:107 -> linux:153 (KEY_DIRECTION) -> xorgevdev:161 */
|
||||
[0x6c] = 0xa9, /* qnum:108 -> linux:161 (KEY_EJECTCD) -> xorgevdev:169 */
|
||||
[0x6d] = 0xc9, /* qnum:109 -> linux:193 (KEY_F23) -> xorgevdev:201 */
|
||||
[0x6f] = 0xca, /* qnum:111 -> linux:194 (KEY_F24) -> xorgevdev:202 */
|
||||
[0x70] = 0xb2, /* qnum:112 -> linux:170 (KEY_ISO) -> xorgevdev:178 */
|
||||
[0x71] = 0xb6, /* qnum:113 -> linux:174 (KEY_EXIT) -> xorgevdev:182 */
|
||||
[0x72] = 0xb7, /* qnum:114 -> linux:175 (KEY_MOVE) -> xorgevdev:183 */
|
||||
[0x73] = 0x61, /* qnum:115 -> linux:89 (KEY_RO) -> xorgevdev:97 */
|
||||
[0x74] = 0xc7, /* qnum:116 -> linux:191 (KEY_F21) -> xorgevdev:199 */
|
||||
[0x75] = 0xb9, /* qnum:117 -> linux:177 (KEY_SCROLLUP) -> xorgevdev:185 */
|
||||
[0x76] = 0x5d, /* qnum:118 -> linux:85 (KEY_ZENKAKUHANKAKU) -> xorgevdev:93 */
|
||||
[0x77] = 0x63, /* qnum:119 -> linux:91 (KEY_HIRAGANA) -> xorgevdev:99 */
|
||||
[0x78] = 0x62, /* qnum:120 -> linux:90 (KEY_KATAKANA) -> xorgevdev:98 */
|
||||
[0x79] = 0x64, /* qnum:121 -> linux:92 (KEY_HENKAN) -> xorgevdev:100 */
|
||||
[0x7b] = 0x66, /* qnum:123 -> linux:94 (KEY_MUHENKAN) -> xorgevdev:102 */
|
||||
[0x7d] = 0x84, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgevdev:132 */
|
||||
[0x7e] = 0x81, /* qnum:126 -> linux:121 (KEY_KPCOMMA) -> xorgevdev:129 */
|
||||
[0x81] = 0xb3, /* qnum:129 -> linux:171 (KEY_CONFIG) -> xorgevdev:179 */
|
||||
[0x82] = 0x9e, /* qnum:130 -> linux:150 (KEY_WWW) -> xorgevdev:158 */
|
||||
[0x83] = 0xc3, /* qnum:131 -> linux:187 (KEY_F17) -> xorgevdev:195 */
|
||||
[0x84] = 0xc5, /* qnum:132 -> linux:189 (KEY_F19) -> xorgevdev:197 */
|
||||
[0x85] = 0x89, /* qnum:133 -> linux:129 (KEY_AGAIN) -> xorgevdev:137 */
|
||||
[0x86] = 0x8a, /* qnum:134 -> linux:130 (KEY_PROPS) -> xorgevdev:138 */
|
||||
[0x87] = 0x8b, /* qnum:135 -> linux:131 (KEY_UNDO) -> xorgevdev:139 */
|
||||
[0x88] = 0xb8, /* qnum:136 -> linux:176 (KEY_EDIT) -> xorgevdev:184 */
|
||||
[0x89] = 0xbd, /* qnum:137 -> linux:181 (KEY_NEW) -> xorgevdev:189 */
|
||||
[0x8a] = 0xbe, /* qnum:138 -> linux:182 (KEY_REDO) -> xorgevdev:190 */
|
||||
[0x8b] = 0x80, /* qnum:139 -> linux:120 (KEY_SCALE) -> xorgevdev:128 */
|
||||
[0x8c] = 0x8c, /* qnum:140 -> linux:132 (KEY_FRONT) -> xorgevdev:140 */
|
||||
[0x8d] = 0x83, /* qnum:141 -> linux:123 (KEY_HANJA) -> xorgevdev:131 */
|
||||
[0x8e] = 0xf1, /* qnum:142 -> linux:233 (KEY_FORWARDMAIL) -> xorgevdev:241 */
|
||||
[0x8f] = 0xba, /* qnum:143 -> linux:178 (KEY_SCROLLDOWN) -> xorgevdev:186 */
|
||||
[0x90] = 0xad, /* qnum:144 -> linux:165 (KEY_PREVIOUSSONG) -> xorgevdev:173 */
|
||||
[0x92] = 0xa0, /* qnum:146 -> linux:152 (KEY_SCREENLOCK) -> xorgevdev:160 */
|
||||
[0x93] = 0x9b, /* qnum:147 -> linux:147 (KEY_XFER) -> xorgevdev:155 */
|
||||
[0x94] = 0xe6, /* qnum:148 -> linux:222 (KEY_ALTERASE) -> xorgevdev:230 */
|
||||
[0x95] = 0xcb, /* qnum:149 -> linux:195 (unnamed) -> xorgevdev:203 */
|
||||
[0x96] = 0xcc, /* qnum:150 -> linux:196 (unnamed) -> xorgevdev:204 */
|
||||
[0x97] = 0x9d, /* qnum:151 -> linux:149 (KEY_PROG2) -> xorgevdev:157 */
|
||||
[0x98] = 0xb0, /* qnum:152 -> linux:168 (KEY_REWIND) -> xorgevdev:176 */
|
||||
[0x99] = 0xab, /* qnum:153 -> linux:163 (KEY_NEXTSONG) -> xorgevdev:171 */
|
||||
[0x9a] = 0xcd, /* qnum:154 -> linux:197 (unnamed) -> xorgevdev:205 */
|
||||
[0x9b] = 0xce, /* qnum:155 -> linux:198 (unnamed) -> xorgevdev:206 */
|
||||
[0x9c] = 0x68, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgevdev:104 */
|
||||
[0x9d] = 0x69, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgevdev:105 */
|
||||
[0x9e] = 0x93, /* qnum:158 -> linux:139 (KEY_MENU) -> xorgevdev:147 */
|
||||
[0x9f] = 0x9c, /* qnum:159 -> linux:148 (KEY_PROG1) -> xorgevdev:156 */
|
||||
[0xa0] = 0x79, /* qnum:160 -> linux:113 (KEY_MUTE) -> xorgevdev:121 */
|
||||
[0xa1] = 0x94, /* qnum:161 -> linux:140 (KEY_CALC) -> xorgevdev:148 */
|
||||
[0xa2] = 0xac, /* qnum:162 -> linux:164 (KEY_PLAYPAUSE) -> xorgevdev:172 */
|
||||
[0xa3] = 0xa8, /* qnum:163 -> linux:160 (KEY_CLOSECD) -> xorgevdev:168 */
|
||||
[0xa4] = 0xae, /* qnum:164 -> linux:166 (KEY_STOPCD) -> xorgevdev:174 */
|
||||
[0xa5] = 0xd5, /* qnum:165 -> linux:205 (KEY_SUSPEND) -> xorgevdev:213 */
|
||||
[0xa6] = 0xa2, /* qnum:166 -> linux:154 (KEY_CYCLEWINDOWS) -> xorgevdev:162 */
|
||||
[0xa7] = 0xcf, /* qnum:167 -> linux:199 (unnamed) -> xorgevdev:207 */
|
||||
[0xa8] = 0xd0, /* qnum:168 -> linux:200 (KEY_PLAYCD) -> xorgevdev:208 */
|
||||
[0xa9] = 0xd1, /* qnum:169 -> linux:201 (KEY_PAUSECD) -> xorgevdev:209 */
|
||||
[0xab] = 0xd2, /* qnum:171 -> linux:202 (KEY_PROG3) -> xorgevdev:210 */
|
||||
[0xac] = 0xd3, /* qnum:172 -> linux:203 (KEY_PROG4) -> xorgevdev:211 */
|
||||
[0xad] = 0xd4, /* qnum:173 -> linux:204 (KEY_DASHBOARD) -> xorgevdev:212 */
|
||||
[0xae] = 0x7a, /* qnum:174 -> linux:114 (KEY_VOLUMEDOWN) -> xorgevdev:122 */
|
||||
[0xaf] = 0xd6, /* qnum:175 -> linux:206 (KEY_CLOSE) -> xorgevdev:214 */
|
||||
[0xb0] = 0x7b, /* qnum:176 -> linux:115 (KEY_VOLUMEUP) -> xorgevdev:123 */
|
||||
[0xb1] = 0xaf, /* qnum:177 -> linux:167 (KEY_RECORD) -> xorgevdev:175 */
|
||||
[0xb2] = 0xb4, /* qnum:178 -> linux:172 (KEY_HOMEPAGE) -> xorgevdev:180 */
|
||||
[0xb3] = 0xd7, /* qnum:179 -> linux:207 (KEY_PLAY) -> xorgevdev:215 */
|
||||
[0xb4] = 0xd8, /* qnum:180 -> linux:208 (KEY_FASTFORWARD) -> xorgevdev:216 */
|
||||
[0xb5] = 0x6a, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgevdev:106 */
|
||||
[0xb6] = 0xd9, /* qnum:182 -> linux:209 (KEY_BASSBOOST) -> xorgevdev:217 */
|
||||
[0xb8] = 0x6c, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgevdev:108 */
|
||||
[0xb9] = 0xda, /* qnum:185 -> linux:210 (KEY_PRINT) -> xorgevdev:218 */
|
||||
[0xba] = 0xdb, /* qnum:186 -> linux:211 (KEY_HP) -> xorgevdev:219 */
|
||||
[0xbb] = 0xdc, /* qnum:187 -> linux:212 (KEY_CAMERA) -> xorgevdev:220 */
|
||||
[0xbc] = 0x91, /* qnum:188 -> linux:137 (KEY_CUT) -> xorgevdev:145 */
|
||||
[0xbd] = 0xdd, /* qnum:189 -> linux:213 (KEY_SOUND) -> xorgevdev:221 */
|
||||
[0xbe] = 0xde, /* qnum:190 -> linux:214 (KEY_QUESTION) -> xorgevdev:222 */
|
||||
[0xbf] = 0xdf, /* qnum:191 -> linux:215 (KEY_EMAIL) -> xorgevdev:223 */
|
||||
[0xc0] = 0xe0, /* qnum:192 -> linux:216 (KEY_CHAT) -> xorgevdev:224 */
|
||||
[0xc1] = 0x90, /* qnum:193 -> linux:136 (KEY_FIND) -> xorgevdev:144 */
|
||||
[0xc2] = 0xe2, /* qnum:194 -> linux:218 (KEY_CONNECT) -> xorgevdev:226 */
|
||||
[0xc3] = 0xe3, /* qnum:195 -> linux:219 (KEY_FINANCE) -> xorgevdev:227 */
|
||||
[0xc4] = 0xe4, /* qnum:196 -> linux:220 (KEY_SPORT) -> xorgevdev:228 */
|
||||
[0xc5] = 0xe5, /* qnum:197 -> linux:221 (KEY_SHOP) -> xorgevdev:229 */
|
||||
[0xc6] = 0x7f, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgevdev:127 */
|
||||
[0xc7] = 0x6e, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgevdev:110 */
|
||||
[0xc8] = 0x6f, /* qnum:200 -> linux:103 (KEY_UP) -> xorgevdev:111 */
|
||||
[0xc9] = 0x70, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgevdev:112 */
|
||||
[0xca] = 0xe7, /* qnum:202 -> linux:223 (KEY_CANCEL) -> xorgevdev:231 */
|
||||
[0xcb] = 0x71, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgevdev:113 */
|
||||
[0xcc] = 0xe8, /* qnum:204 -> linux:224 (KEY_BRIGHTNESSDOWN) -> xorgevdev:232 */
|
||||
[0xcd] = 0x72, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgevdev:114 */
|
||||
[0xce] = 0x7e, /* qnum:206 -> linux:118 (KEY_KPPLUSMINUS) -> xorgevdev:126 */
|
||||
[0xcf] = 0x73, /* qnum:207 -> linux:107 (KEY_END) -> xorgevdev:115 */
|
||||
[0xd0] = 0x74, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgevdev:116 */
|
||||
[0xd1] = 0x75, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgevdev:117 */
|
||||
[0xd2] = 0x76, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgevdev:118 */
|
||||
[0xd3] = 0x77, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgevdev:119 */
|
||||
[0xd4] = 0xe9, /* qnum:212 -> linux:225 (KEY_BRIGHTNESSUP) -> xorgevdev:233 */
|
||||
[0xd5] = 0xf2, /* qnum:213 -> linux:234 (KEY_SAVE) -> xorgevdev:242 */
|
||||
[0xd6] = 0xeb, /* qnum:214 -> linux:227 (KEY_SWITCHVIDEOMODE) -> xorgevdev:235 */
|
||||
[0xd7] = 0xec, /* qnum:215 -> linux:228 (KEY_KBDILLUMTOGGLE) -> xorgevdev:236 */
|
||||
[0xd8] = 0xed, /* qnum:216 -> linux:229 (KEY_KBDILLUMDOWN) -> xorgevdev:237 */
|
||||
[0xd9] = 0xee, /* qnum:217 -> linux:230 (KEY_KBDILLUMUP) -> xorgevdev:238 */
|
||||
[0xda] = 0xef, /* qnum:218 -> linux:231 (KEY_SEND) -> xorgevdev:239 */
|
||||
[0xdb] = 0x85, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgevdev:133 */
|
||||
[0xdc] = 0x86, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgevdev:134 */
|
||||
[0xdd] = 0x87, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgevdev:135 */
|
||||
[0xde] = 0x7c, /* qnum:222 -> linux:116 (KEY_POWER) -> xorgevdev:124 */
|
||||
[0xdf] = 0x96, /* qnum:223 -> linux:142 (KEY_SLEEP) -> xorgevdev:150 */
|
||||
[0xe3] = 0x97, /* qnum:227 -> linux:143 (KEY_WAKEUP) -> xorgevdev:151 */
|
||||
[0xe4] = 0xf0, /* qnum:228 -> linux:232 (KEY_REPLY) -> xorgevdev:240 */
|
||||
[0xe5] = 0xe1, /* qnum:229 -> linux:217 (KEY_SEARCH) -> xorgevdev:225 */
|
||||
[0xe6] = 0xa4, /* qnum:230 -> linux:156 (KEY_BOOKMARKS) -> xorgevdev:164 */
|
||||
[0xe7] = 0xb5, /* qnum:231 -> linux:173 (KEY_REFRESH) -> xorgevdev:181 */
|
||||
[0xe8] = 0x88, /* qnum:232 -> linux:128 (KEY_STOP) -> xorgevdev:136 */
|
||||
[0xe9] = 0xa7, /* qnum:233 -> linux:159 (KEY_FORWARD) -> xorgevdev:167 */
|
||||
[0xea] = 0xa6, /* qnum:234 -> linux:158 (KEY_BACK) -> xorgevdev:166 */
|
||||
[0xeb] = 0xa5, /* qnum:235 -> linux:157 (KEY_COMPUTER) -> xorgevdev:165 */
|
||||
[0xec] = 0xa3, /* qnum:236 -> linux:155 (KEY_MAIL) -> xorgevdev:163 */
|
||||
[0xed] = 0xea, /* qnum:237 -> linux:226 (KEY_MEDIA) -> xorgevdev:234 */
|
||||
[0xef] = 0x78, /* qnum:239 -> linux:112 (KEY_MACRO) -> xorgevdev:120 */
|
||||
[0xf0] = 0xf3, /* qnum:240 -> linux:235 (KEY_DOCUMENTS) -> xorgevdev:243 */
|
||||
[0xf1] = 0xf4, /* qnum:241 -> linux:236 (KEY_BATTERY) -> xorgevdev:244 */
|
||||
[0xf2] = 0xf5, /* qnum:242 -> linux:237 (KEY_BLUETOOTH) -> xorgevdev:245 */
|
||||
[0xf3] = 0xf6, /* qnum:243 -> linux:238 (KEY_WLAN) -> xorgevdev:246 */
|
||||
[0xf4] = 0xf7, /* qnum:244 -> linux:239 (KEY_UWB) -> xorgevdev:247 */
|
||||
[0xf5] = 0x92, /* qnum:245 -> linux:138 (KEY_HELP) -> xorgevdev:146 */
|
||||
[0xf6] = 0xbb, /* qnum:246 -> linux:179 (KEY_KPLEFTPAREN) -> xorgevdev:187 */
|
||||
[0xf7] = 0xc4, /* qnum:247 -> linux:188 (KEY_F18) -> xorgevdev:196 */
|
||||
[0xf8] = 0x8d, /* qnum:248 -> linux:133 (KEY_COPY) -> xorgevdev:141 */
|
||||
[0xf9] = 0xc8, /* qnum:249 -> linux:192 (KEY_F22) -> xorgevdev:200 */
|
||||
[0xfb] = 0xbc, /* qnum:251 -> linux:180 (KEY_KPRIGHTPAREN) -> xorgevdev:188 */
|
||||
[0xfd] = 0xaa, /* qnum:253 -> linux:162 (KEY_EJECTCLOSECD) -> xorgevdev:170 */
|
||||
};
|
||||
const unsigned int code_map_qnum_to_xorgevdev_len = sizeof(code_map_qnum_to_xorgevdev)/sizeof(code_map_qnum_to_xorgevdev[0]);
|
||||
121
unix/xserver/hw/vnc/qnum_to_xorgkbd.c
Normal file
121
unix/xserver/hw/vnc/qnum_to_xorgkbd.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is auto-generated from keymaps.csv on 2017-08-28 13:04
|
||||
* Database checksum sha256(f8aeff0c3430077a350e3d7ba2b335b381bd929ac4b193413730a402ff3f0097)
|
||||
* To re-generate, run:
|
||||
* keymap-gen --lang=stdc code-map keymaps.csv qnum xorgkbd
|
||||
*/
|
||||
const unsigned short code_map_qnum_to_xorgkbd[254] = {
|
||||
[0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgkbd:9 */
|
||||
[0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgkbd:10 */
|
||||
[0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgkbd:11 */
|
||||
[0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgkbd:12 */
|
||||
[0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgkbd:13 */
|
||||
[0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgkbd:14 */
|
||||
[0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgkbd:15 */
|
||||
[0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgkbd:16 */
|
||||
[0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgkbd:17 */
|
||||
[0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgkbd:18 */
|
||||
[0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgkbd:19 */
|
||||
[0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgkbd:20 */
|
||||
[0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgkbd:21 */
|
||||
[0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgkbd:22 */
|
||||
[0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgkbd:23 */
|
||||
[0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgkbd:24 */
|
||||
[0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgkbd:25 */
|
||||
[0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgkbd:26 */
|
||||
[0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgkbd:27 */
|
||||
[0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgkbd:28 */
|
||||
[0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgkbd:29 */
|
||||
[0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgkbd:30 */
|
||||
[0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgkbd:31 */
|
||||
[0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgkbd:32 */
|
||||
[0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgkbd:33 */
|
||||
[0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgkbd:34 */
|
||||
[0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgkbd:35 */
|
||||
[0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgkbd:36 */
|
||||
[0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgkbd:37 */
|
||||
[0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgkbd:38 */
|
||||
[0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgkbd:39 */
|
||||
[0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgkbd:40 */
|
||||
[0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgkbd:41 */
|
||||
[0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgkbd:42 */
|
||||
[0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgkbd:43 */
|
||||
[0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgkbd:44 */
|
||||
[0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgkbd:45 */
|
||||
[0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgkbd:46 */
|
||||
[0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgkbd:47 */
|
||||
[0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgkbd:48 */
|
||||
[0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgkbd:49 */
|
||||
[0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgkbd:50 */
|
||||
[0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgkbd:51 */
|
||||
[0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgkbd:52 */
|
||||
[0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgkbd:53 */
|
||||
[0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgkbd:54 */
|
||||
[0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgkbd:55 */
|
||||
[0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgkbd:56 */
|
||||
[0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgkbd:57 */
|
||||
[0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgkbd:58 */
|
||||
[0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgkbd:59 */
|
||||
[0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgkbd:60 */
|
||||
[0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgkbd:61 */
|
||||
[0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgkbd:62 */
|
||||
[0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgkbd:63 */
|
||||
[0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgkbd:64 */
|
||||
[0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgkbd:65 */
|
||||
[0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgkbd:66 */
|
||||
[0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgkbd:67 */
|
||||
[0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgkbd:68 */
|
||||
[0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgkbd:69 */
|
||||
[0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgkbd:70 */
|
||||
[0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgkbd:71 */
|
||||
[0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgkbd:72 */
|
||||
[0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgkbd:73 */
|
||||
[0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgkbd:74 */
|
||||
[0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgkbd:75 */
|
||||
[0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgkbd:76 */
|
||||
[0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgkbd:77 */
|
||||
[0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgkbd:78 */
|
||||
[0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgkbd:79 */
|
||||
[0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgkbd:80 */
|
||||
[0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgkbd:81 */
|
||||
[0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgkbd:82 */
|
||||
[0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgkbd:83 */
|
||||
[0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgkbd:84 */
|
||||
[0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgkbd:85 */
|
||||
[0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgkbd:86 */
|
||||
[0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgkbd:87 */
|
||||
[0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgkbd:88 */
|
||||
[0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgkbd:89 */
|
||||
[0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgkbd:90 */
|
||||
[0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgkbd:91 */
|
||||
[0x54] = 0x6f, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgkbd:111 */
|
||||
[0x55] = 0x79, /* qnum:85 -> linux:186 (KEY_F16) -> xorgkbd:121 */
|
||||
[0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgkbd:94 */
|
||||
[0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgkbd:95 */
|
||||
[0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgkbd:96 */
|
||||
[0x59] = 0x7e, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgkbd:126 */
|
||||
[0x5d] = 0x76, /* qnum:93 -> linux:183 (KEY_F13) -> xorgkbd:118 */
|
||||
[0x5e] = 0x77, /* qnum:94 -> linux:184 (KEY_F14) -> xorgkbd:119 */
|
||||
[0x5f] = 0x78, /* qnum:95 -> linux:185 (KEY_F15) -> xorgkbd:120 */
|
||||
[0x7d] = 0x85, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgkbd:133 */
|
||||
[0x83] = 0x7a, /* qnum:131 -> linux:187 (KEY_F17) -> xorgkbd:122 */
|
||||
[0x9c] = 0x6c, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgkbd:108 */
|
||||
[0x9d] = 0x6d, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgkbd:109 */
|
||||
[0xb5] = 0x70, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgkbd:112 */
|
||||
[0xb8] = 0x71, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgkbd:113 */
|
||||
[0xc6] = 0x6e, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgkbd:110 */
|
||||
[0xc7] = 0x61, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgkbd:97 */
|
||||
[0xc8] = 0x62, /* qnum:200 -> linux:103 (KEY_UP) -> xorgkbd:98 */
|
||||
[0xc9] = 0x63, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgkbd:99 */
|
||||
[0xcb] = 0x64, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgkbd:100 */
|
||||
[0xcd] = 0x66, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgkbd:102 */
|
||||
[0xcf] = 0x67, /* qnum:207 -> linux:107 (KEY_END) -> xorgkbd:103 */
|
||||
[0xd0] = 0x68, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgkbd:104 */
|
||||
[0xd1] = 0x69, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgkbd:105 */
|
||||
[0xd2] = 0x6a, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgkbd:106 */
|
||||
[0xd3] = 0x6b, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgkbd:107 */
|
||||
[0xdb] = 0x73, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgkbd:115 */
|
||||
[0xdc] = 0x74, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgkbd:116 */
|
||||
[0xdd] = 0x75, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgkbd:117 */
|
||||
};
|
||||
const unsigned int code_map_qnum_to_xorgkbd_len = sizeof(code_map_qnum_to_xorgkbd)/sizeof(code_map_qnum_to_xorgkbd[0]);
|
||||
296
unix/xserver/hw/vnc/vncBlockHandler.c
Normal file
296
unix/xserver/hw/vnc/vncBlockHandler.c
Normal file
@@ -0,0 +1,296 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2014 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xpoll.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "dix.h"
|
||||
#include "scrnintstr.h"
|
||||
|
||||
#include "vncExtInit.h"
|
||||
#include "vncBlockHandler.h"
|
||||
#include "xorg-version.h"
|
||||
|
||||
#if XORG >= 119
|
||||
static void vncBlockHandler(void* data, void* timeout);
|
||||
static void vncSocketNotify(int fd, int xevents, void *data);
|
||||
#else
|
||||
static void vncBlockHandler(void * data, OSTimePtr t, void * readmask);
|
||||
static void vncWakeupHandler(void * data, int nfds, void * readmask);
|
||||
|
||||
struct vncFdEntry {
|
||||
int fd;
|
||||
int read, write;
|
||||
int scrIdx;
|
||||
struct vncFdEntry* next;
|
||||
};
|
||||
|
||||
static struct vncFdEntry* fdsHead = NULL;
|
||||
#endif
|
||||
|
||||
void vncRegisterBlockHandlers(void)
|
||||
{
|
||||
if (!RegisterBlockAndWakeupHandlers(vncBlockHandler,
|
||||
#if XORG >= 119
|
||||
(ServerWakeupHandlerProcPtr)NoopDDA,
|
||||
#else
|
||||
vncWakeupHandler,
|
||||
#endif
|
||||
0))
|
||||
FatalError("RegisterBlockAndWakeupHandlers() failed\n");
|
||||
}
|
||||
|
||||
void vncSetNotifyFd(int fd, int scrIdx, int read, int write)
|
||||
{
|
||||
#if XORG >= 119
|
||||
int mask = (read ? X_NOTIFY_READ : 0) | (write ? X_NOTIFY_WRITE : 0);
|
||||
SetNotifyFd(fd, vncSocketNotify, mask, (void*)(intptr_t)scrIdx);
|
||||
#else
|
||||
struct vncFdEntry* entry;
|
||||
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->fd == fd) {
|
||||
assert(entry->scrIdx == scrIdx);
|
||||
entry->read = read;
|
||||
entry->write = write;
|
||||
return;
|
||||
}
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
entry = malloc(sizeof(struct vncFdEntry));
|
||||
memset(entry, 0, sizeof(struct vncFdEntry));
|
||||
|
||||
entry->fd = fd;
|
||||
entry->scrIdx = scrIdx;
|
||||
entry->read = read;
|
||||
entry->write = write;
|
||||
|
||||
entry->next = fdsHead;
|
||||
fdsHead = entry;
|
||||
#endif
|
||||
}
|
||||
|
||||
void vncRemoveNotifyFd(int fd)
|
||||
{
|
||||
#if XORG >= 119
|
||||
RemoveNotifyFd(fd);
|
||||
#else
|
||||
struct vncFdEntry** prev;
|
||||
struct vncFdEntry* entry;
|
||||
|
||||
prev = &fdsHead;
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->fd == fd) {
|
||||
*prev = entry->next;
|
||||
return;
|
||||
}
|
||||
prev = &entry->next;
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
assert(FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XORG >= 119
|
||||
static void vncSocketNotify(int fd, int xevents, void *data)
|
||||
{
|
||||
int scrIdx;
|
||||
|
||||
scrIdx = (intptr_t)data;
|
||||
vncHandleSocketEvent(fd, scrIdx,
|
||||
xevents & X_NOTIFY_READ,
|
||||
xevents & X_NOTIFY_WRITE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XORG < 119
|
||||
static void vncWriteBlockHandlerFallback(OSTimePtr timeout);
|
||||
static void vncWriteWakeupHandlerFallback(void);
|
||||
void vncWriteBlockHandler(fd_set *fds);
|
||||
void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
#endif
|
||||
|
||||
//
|
||||
// vncBlockHandler - called just before the X server goes into poll().
|
||||
//
|
||||
// For older versions of X this also allows us to register file
|
||||
// descriptors that we want read events on.
|
||||
//
|
||||
|
||||
#if XORG >= 119
|
||||
static void vncBlockHandler(void* data, void* timeout)
|
||||
#else
|
||||
static void vncBlockHandler(void * data, OSTimePtr t, void * readmask)
|
||||
#endif
|
||||
{
|
||||
#if XORG < 119
|
||||
int _timeout;
|
||||
int* timeout = &_timeout;
|
||||
static struct timeval tv;
|
||||
|
||||
fd_set* fds;
|
||||
static struct vncFdEntry* entry;
|
||||
|
||||
if (*t == NULL)
|
||||
_timeout = -1;
|
||||
else
|
||||
_timeout = (*t)->tv_sec * 1000 + (*t)->tv_usec / 1000;
|
||||
#endif
|
||||
|
||||
vncCallBlockHandlers(timeout);
|
||||
|
||||
#if XORG < 119
|
||||
if (_timeout != -1) {
|
||||
tv.tv_sec= _timeout / 1000;
|
||||
tv.tv_usec = (_timeout % 1000) * 1000;
|
||||
*t = &tv;
|
||||
}
|
||||
|
||||
fds = (fd_set*)readmask;
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->read)
|
||||
FD_SET(entry->fd, fds);
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
vncWriteBlockHandlerFallback(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XORG < 119
|
||||
static void vncWakeupHandler(void * data, int nfds, void * readmask)
|
||||
{
|
||||
fd_set* fds = (fd_set*)readmask;
|
||||
|
||||
static struct vncFdEntry* entry;
|
||||
|
||||
if (nfds <= 0)
|
||||
return;
|
||||
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->read && FD_ISSET(entry->fd, fds))
|
||||
vncHandleSocketEvent(entry->fd, entry->scrIdx, TRUE, FALSE);
|
||||
entry = entry->next;
|
||||
}
|
||||
|
||||
vncWriteWakeupHandlerFallback();
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// vncWriteBlockHandler - extra hack to be able to get old versions of the X
|
||||
// server to monitor writeable fds and not just readable. This requirers a
|
||||
// modified Xorg and might therefore not be called.
|
||||
//
|
||||
|
||||
#if XORG < 119
|
||||
static Bool needFallback = TRUE;
|
||||
static fd_set fallbackFds;
|
||||
static struct timeval tw;
|
||||
|
||||
void vncWriteBlockHandler(fd_set *fds)
|
||||
{
|
||||
static struct vncFdEntry* entry;
|
||||
|
||||
needFallback = FALSE;
|
||||
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->write)
|
||||
FD_SET(entry->fd, fds);
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
void vncWriteWakeupHandler(int nfds, fd_set *fds)
|
||||
{
|
||||
static struct vncFdEntry* entry;
|
||||
|
||||
if (nfds <= 0)
|
||||
return;
|
||||
|
||||
entry = fdsHead;
|
||||
while (entry) {
|
||||
if (entry->write && FD_ISSET(entry->fd, fds))
|
||||
vncHandleSocketEvent(entry->fd, entry->scrIdx, FALSE, TRUE);
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void vncWriteBlockHandlerFallback(OSTimePtr timeout)
|
||||
{
|
||||
if (!needFallback)
|
||||
return;
|
||||
|
||||
FD_ZERO(&fallbackFds);
|
||||
vncWriteBlockHandler(&fallbackFds);
|
||||
|
||||
// vncWriteBlockHandler() will clear this, so we need to restore it
|
||||
needFallback = TRUE;
|
||||
|
||||
if (!XFD_ANYSET(&fallbackFds))
|
||||
return;
|
||||
|
||||
if ((*timeout == NULL) ||
|
||||
((*timeout)->tv_sec > 0) || ((*timeout)->tv_usec > 10000)) {
|
||||
tw.tv_sec = 0;
|
||||
tw.tv_usec = 10000;
|
||||
*timeout = &tw;
|
||||
}
|
||||
}
|
||||
|
||||
static void vncWriteWakeupHandlerFallback(void)
|
||||
{
|
||||
int ret;
|
||||
struct timeval timeout;
|
||||
|
||||
if (!needFallback)
|
||||
return;
|
||||
|
||||
if (!XFD_ANYSET(&fallbackFds))
|
||||
return;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
ret = select(XFD_SETSIZE, NULL, &fallbackFds, NULL, &timeout);
|
||||
if (ret < 0) {
|
||||
ErrorF("vncWriteWakeupHandlerFallback(): select: %s\n",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return;
|
||||
|
||||
vncWriteWakeupHandler(ret, &fallbackFds);
|
||||
}
|
||||
#endif
|
||||
36
unix/xserver/hw/vnc/vncBlockHandler.h
Normal file
36
unix/xserver/hw/vnc/vncBlockHandler.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2014 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef VNCBLOCKHANDLER_H
|
||||
#define VNCBLOCKHANDLER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void vncRegisterBlockHandlers(void);
|
||||
|
||||
void vncSetNotifyFd(int fd, int scrIdx, int read, int write);
|
||||
void vncRemoveNotifyFd(int fd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
605
unix/xserver/hw/vnc/vncExt.c
Normal file
605
unix/xserver/hw/vnc/vncExt.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#define NEED_EVENTS
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
#include "dixstruct.h"
|
||||
#include "extnsionst.h"
|
||||
#include "scrnintstr.h"
|
||||
|
||||
#define _VNCEXT_SERVER_
|
||||
#define _VNCEXT_PROTO_
|
||||
#include "vncExt.h"
|
||||
|
||||
#include "xorg-version.h"
|
||||
|
||||
#include "vncExtInit.h"
|
||||
#include "RFBGlue.h"
|
||||
|
||||
static int ProcVncExtDispatch(ClientPtr client);
|
||||
static int SProcVncExtDispatch(ClientPtr client);
|
||||
static void vncResetProc(ExtensionEntry* extEntry);
|
||||
|
||||
static void vncClientStateChange(CallbackListPtr*, void *, void *);
|
||||
|
||||
static int vncErrorBase = 0;
|
||||
static int vncEventBase = 0;
|
||||
|
||||
int vncNoClipboard = 0;
|
||||
|
||||
static struct VncInputSelect* vncInputSelectHead = NULL;
|
||||
|
||||
struct VncInputSelect {
|
||||
ClientPtr client;
|
||||
Window window;
|
||||
int mask;
|
||||
struct VncInputSelect* next;
|
||||
};
|
||||
|
||||
void vncAddExtension(void)
|
||||
{
|
||||
ExtensionEntry* extEntry;
|
||||
|
||||
extEntry = AddExtension(VNCEXTNAME, VncExtNumberEvents, VncExtNumberErrors,
|
||||
ProcVncExtDispatch, SProcVncExtDispatch, vncResetProc,
|
||||
StandardMinorOpcode);
|
||||
if (!extEntry) {
|
||||
FatalError("vncAddExtension: AddExtension failed\n");
|
||||
}
|
||||
|
||||
vncErrorBase = extEntry->errorBase;
|
||||
vncEventBase = extEntry->eventBase;
|
||||
|
||||
if (!AddCallback(&ClientStateCallback, vncClientStateChange, 0)) {
|
||||
FatalError("Add ClientStateCallback failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
int vncNotifyQueryConnect(void)
|
||||
{
|
||||
int count;
|
||||
xVncExtQueryConnectNotifyEvent ev;
|
||||
|
||||
ev.type = vncEventBase + VncExtQueryConnectNotify;
|
||||
|
||||
count = 0;
|
||||
for (struct VncInputSelect* cur = vncInputSelectHead; cur; cur = cur->next) {
|
||||
if (cur->mask & VncExtQueryConnectMask) {
|
||||
ev.sequenceNumber = cur->client->sequence;
|
||||
ev.window = cur->window;
|
||||
if (cur->client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&ev.sequenceNumber, n);
|
||||
swapl(&ev.window, n);
|
||||
#else
|
||||
swaps(&ev.sequenceNumber);
|
||||
swapl(&ev.window);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(cur->client, sizeof(xVncExtQueryConnectNotifyEvent),
|
||||
(char *)&ev);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int ProcVncExtSetParam(ClientPtr client)
|
||||
{
|
||||
char *param;
|
||||
xVncExtSetParamReply rep;
|
||||
|
||||
REQUEST(xVncExtSetParamReq);
|
||||
REQUEST_FIXED_SIZE(xVncExtSetParamReq, stuff->paramLen);
|
||||
|
||||
param = malloc(stuff->paramLen+1);
|
||||
if (param == NULL)
|
||||
return BadAlloc;
|
||||
strncpy(param, (char*)&stuff[1], stuff->paramLen);
|
||||
param[stuff->paramLen] = '\0';
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.success = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
|
||||
/*
|
||||
* Prevent change of clipboard related parameters if clipboard is disabled.
|
||||
*/
|
||||
if (vncNoClipboard &&
|
||||
(strncasecmp(param, "SendCutText", 11) == 0 ||
|
||||
strncasecmp(param, "AcceptCutText", 13) == 0))
|
||||
goto deny;
|
||||
|
||||
if (!vncOverrideParam(param))
|
||||
goto deny;
|
||||
|
||||
rep.success = 1;
|
||||
|
||||
// Send DesktopName update if desktop name has been changed
|
||||
if (strncasecmp(param, "desktop", 7) == 0)
|
||||
vncUpdateDesktopName();
|
||||
|
||||
deny:
|
||||
free(param);
|
||||
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.length, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtSetParamReply), (char *)&rep);
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtSetParam(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtSetParamReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_AT_LEAST_SIZE(xVncExtSetParamReq);
|
||||
return ProcVncExtSetParam(client);
|
||||
}
|
||||
|
||||
static int ProcVncExtGetParam(ClientPtr client)
|
||||
{
|
||||
char* param;
|
||||
char* value;
|
||||
size_t len;
|
||||
xVncExtGetParamReply rep;
|
||||
|
||||
REQUEST(xVncExtGetParamReq);
|
||||
REQUEST_FIXED_SIZE(xVncExtGetParamReq, stuff->paramLen);
|
||||
|
||||
param = malloc(stuff->paramLen+1);
|
||||
if (param == NULL)
|
||||
return BadAlloc;
|
||||
strncpy(param, (char*)&stuff[1], stuff->paramLen);
|
||||
param[stuff->paramLen] = 0;
|
||||
|
||||
value = vncGetParam(param);
|
||||
len = value ? strlen(value) : 0;
|
||||
|
||||
free(param);
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.success = 0;
|
||||
if (value)
|
||||
rep.success = 1;
|
||||
rep.length = (len + 3) >> 2;
|
||||
rep.valueLen = len;
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.length, n);
|
||||
swaps(&rep.valueLen, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swaps(&rep.valueLen);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtGetParamReply), (char *)&rep);
|
||||
if (value)
|
||||
WriteToClient(client, len, value);
|
||||
free(value);
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtGetParam(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtGetParamReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_AT_LEAST_SIZE(xVncExtGetParamReq);
|
||||
return ProcVncExtGetParam(client);
|
||||
}
|
||||
|
||||
static int ProcVncExtGetParamDesc(ClientPtr client)
|
||||
{
|
||||
char* param;
|
||||
const char* desc;
|
||||
size_t len;
|
||||
xVncExtGetParamDescReply rep;
|
||||
|
||||
REQUEST(xVncExtGetParamDescReq);
|
||||
REQUEST_FIXED_SIZE(xVncExtGetParamDescReq, stuff->paramLen);
|
||||
|
||||
param = malloc(stuff->paramLen+1);
|
||||
if (param == NULL)
|
||||
return BadAlloc;
|
||||
strncpy(param, (char*)&stuff[1], stuff->paramLen);
|
||||
param[stuff->paramLen] = 0;
|
||||
|
||||
desc = vncGetParamDesc(param);
|
||||
len = desc ? strlen(desc) : 0;
|
||||
|
||||
free(param);
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.success = 0;
|
||||
if (desc)
|
||||
rep.success = 1;
|
||||
rep.length = (len + 3) >> 2;
|
||||
rep.descLen = len;
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.length, n);
|
||||
swaps(&rep.descLen, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swaps(&rep.descLen);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtGetParamDescReply), (char *)&rep);
|
||||
if (desc)
|
||||
WriteToClient(client, len, desc);
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtGetParamDesc(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtGetParamDescReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_AT_LEAST_SIZE(xVncExtGetParamDescReq);
|
||||
return ProcVncExtGetParamDesc(client);
|
||||
}
|
||||
|
||||
static int ProcVncExtListParams(ClientPtr client)
|
||||
{
|
||||
xVncExtListParamsReply rep;
|
||||
char *params;
|
||||
size_t len;
|
||||
|
||||
REQUEST_SIZE_MATCH(xVncExtListParamsReq);
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
|
||||
params = vncGetParamList();
|
||||
if (params == NULL)
|
||||
return BadAlloc;
|
||||
|
||||
len = strlen(params);
|
||||
|
||||
rep.length = (len + 3) >> 2;
|
||||
rep.nParams = vncGetParamCount();
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.length, n);
|
||||
swaps(&rep.nParams, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swaps(&rep.nParams);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtListParamsReply), (char *)&rep);
|
||||
WriteToClient(client, len, (char*)params);
|
||||
free(params);
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtListParams(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtListParamsReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_SIZE_MATCH(xVncExtListParamsReq);
|
||||
return ProcVncExtListParams(client);
|
||||
}
|
||||
|
||||
static int ProcVncExtSelectInput(ClientPtr client)
|
||||
{
|
||||
struct VncInputSelect** nextPtr;
|
||||
struct VncInputSelect* cur;
|
||||
REQUEST(xVncExtSelectInputReq);
|
||||
REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
|
||||
nextPtr = &vncInputSelectHead;
|
||||
for (cur = vncInputSelectHead; cur; cur = *nextPtr) {
|
||||
if (cur->client == client && cur->window == stuff->window) {
|
||||
cur->mask = stuff->mask;
|
||||
if (!cur->mask) {
|
||||
*nextPtr = cur->next;
|
||||
free(cur);
|
||||
}
|
||||
break;
|
||||
}
|
||||
nextPtr = &cur->next;
|
||||
}
|
||||
if (!cur) {
|
||||
cur = malloc(sizeof(struct VncInputSelect));
|
||||
if (cur == NULL)
|
||||
return BadAlloc;
|
||||
memset(cur, 0, sizeof(struct VncInputSelect));
|
||||
|
||||
cur->client = client;
|
||||
cur->window = stuff->window;
|
||||
cur->mask = stuff->mask;
|
||||
|
||||
cur->next = vncInputSelectHead;
|
||||
vncInputSelectHead = cur;
|
||||
}
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtSelectInput(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtSelectInputReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_SIZE_MATCH(xVncExtSelectInputReq);
|
||||
#if XORG < 112
|
||||
swapl(&stuff->window, n);
|
||||
swapl(&stuff->mask, n);
|
||||
#else
|
||||
swapl(&stuff->window);
|
||||
swapl(&stuff->mask);
|
||||
#endif
|
||||
return ProcVncExtSelectInput(client);
|
||||
}
|
||||
|
||||
static int ProcVncExtConnect(ClientPtr client)
|
||||
{
|
||||
char *address;
|
||||
xVncExtConnectReply rep;
|
||||
|
||||
REQUEST(xVncExtConnectReq);
|
||||
REQUEST_FIXED_SIZE(xVncExtConnectReq, stuff->strLen);
|
||||
|
||||
address = malloc(stuff->strLen+1);
|
||||
if (address == NULL)
|
||||
return BadAlloc;
|
||||
strncpy(address, (char*)&stuff[1], stuff->strLen);
|
||||
address[stuff->strLen] = 0;
|
||||
|
||||
rep.success = 0;
|
||||
if (vncConnectClient(address) == 0)
|
||||
rep.success = 1;
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.length = 0;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.length, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtConnectReply), (char *)&rep);
|
||||
|
||||
free(address);
|
||||
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtConnect(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtConnectReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_AT_LEAST_SIZE(xVncExtConnectReq);
|
||||
return ProcVncExtConnect(client);
|
||||
}
|
||||
|
||||
|
||||
static int ProcVncExtGetQueryConnect(ClientPtr client)
|
||||
{
|
||||
uint32_t opaqueId;
|
||||
const char *qcAddress, *qcUsername;
|
||||
int qcTimeout;
|
||||
|
||||
xVncExtGetQueryConnectReply rep;
|
||||
|
||||
REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
|
||||
|
||||
vncGetQueryConnect(&opaqueId, &qcAddress, &qcUsername, &qcTimeout);
|
||||
|
||||
rep.type = X_Reply;
|
||||
rep.sequenceNumber = client->sequence;
|
||||
rep.timeout = qcTimeout;
|
||||
rep.addrLen = qcTimeout ? strlen(qcAddress) : 0;
|
||||
rep.userLen = qcTimeout ? strlen(qcUsername) : 0;
|
||||
rep.opaqueId = (CARD32)(long)opaqueId;
|
||||
rep.length = ((rep.userLen + 3) >> 2) + ((rep.addrLen + 3) >> 2);
|
||||
if (client->swapped) {
|
||||
#if XORG < 112
|
||||
int n;
|
||||
swaps(&rep.sequenceNumber, n);
|
||||
swapl(&rep.addrLen, n);
|
||||
swapl(&rep.userLen, n);
|
||||
swapl(&rep.timeout, n);
|
||||
swapl(&rep.opaqueId, n);
|
||||
swapl(&rep.length, n);
|
||||
#else
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.addrLen);
|
||||
swapl(&rep.userLen);
|
||||
swapl(&rep.timeout);
|
||||
swapl(&rep.opaqueId);
|
||||
swapl(&rep.length);
|
||||
#endif
|
||||
}
|
||||
WriteToClient(client, sizeof(xVncExtGetQueryConnectReply), (char *)&rep);
|
||||
if (qcTimeout)
|
||||
WriteToClient(client, strlen(qcAddress), qcAddress);
|
||||
if (qcTimeout)
|
||||
WriteToClient(client, strlen(qcUsername), qcUsername);
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtGetQueryConnect(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtGetQueryConnectReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
#endif
|
||||
REQUEST_SIZE_MATCH(xVncExtGetQueryConnectReq);
|
||||
return ProcVncExtGetQueryConnect(client);
|
||||
}
|
||||
|
||||
|
||||
static int ProcVncExtApproveConnect(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtApproveConnectReq);
|
||||
REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
|
||||
vncApproveConnection(stuff->opaqueId, stuff->approve);
|
||||
// Inform other clients of the event and tidy up
|
||||
vncNotifyQueryConnect();
|
||||
return (client->noClientException);
|
||||
}
|
||||
|
||||
static int SProcVncExtApproveConnect(ClientPtr client)
|
||||
{
|
||||
REQUEST(xVncExtApproveConnectReq);
|
||||
#if XORG < 112
|
||||
register char n;
|
||||
swaps(&stuff->length, n);
|
||||
swapl(&stuff->opaqueId, n);
|
||||
#else
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->opaqueId);
|
||||
#endif
|
||||
REQUEST_SIZE_MATCH(xVncExtApproveConnectReq);
|
||||
return ProcVncExtApproveConnect(client);
|
||||
}
|
||||
|
||||
|
||||
static int ProcVncExtDispatch(ClientPtr client)
|
||||
{
|
||||
REQUEST(xReq);
|
||||
switch (stuff->data) {
|
||||
case X_VncExtSetParam:
|
||||
return ProcVncExtSetParam(client);
|
||||
case X_VncExtGetParam:
|
||||
return ProcVncExtGetParam(client);
|
||||
case X_VncExtGetParamDesc:
|
||||
return ProcVncExtGetParamDesc(client);
|
||||
case X_VncExtListParams:
|
||||
return ProcVncExtListParams(client);
|
||||
case X_VncExtSelectInput:
|
||||
return ProcVncExtSelectInput(client);
|
||||
case X_VncExtConnect:
|
||||
return ProcVncExtConnect(client);
|
||||
case X_VncExtGetQueryConnect:
|
||||
return ProcVncExtGetQueryConnect(client);
|
||||
case X_VncExtApproveConnect:
|
||||
return ProcVncExtApproveConnect(client);
|
||||
default:
|
||||
return BadRequest;
|
||||
}
|
||||
}
|
||||
|
||||
static int SProcVncExtDispatch(ClientPtr client)
|
||||
{
|
||||
REQUEST(xReq);
|
||||
switch (stuff->data) {
|
||||
case X_VncExtSetParam:
|
||||
return SProcVncExtSetParam(client);
|
||||
case X_VncExtGetParam:
|
||||
return SProcVncExtGetParam(client);
|
||||
case X_VncExtGetParamDesc:
|
||||
return SProcVncExtGetParamDesc(client);
|
||||
case X_VncExtListParams:
|
||||
return SProcVncExtListParams(client);
|
||||
case X_VncExtSelectInput:
|
||||
return SProcVncExtSelectInput(client);
|
||||
case X_VncExtConnect:
|
||||
return SProcVncExtConnect(client);
|
||||
case X_VncExtGetQueryConnect:
|
||||
return SProcVncExtGetQueryConnect(client);
|
||||
case X_VncExtApproveConnect:
|
||||
return SProcVncExtApproveConnect(client);
|
||||
default:
|
||||
return BadRequest;
|
||||
}
|
||||
}
|
||||
|
||||
static void vncResetProc(ExtensionEntry* extEntry)
|
||||
{
|
||||
vncExtensionClose();
|
||||
}
|
||||
|
||||
static void vncClientStateChange(CallbackListPtr * l, void * d, void * p)
|
||||
{
|
||||
ClientPtr client = ((NewClientInfoRec*)p)->client;
|
||||
if (client->clientState == ClientStateGone) {
|
||||
struct VncInputSelect** nextPtr = &vncInputSelectHead;
|
||||
for (struct VncInputSelect* cur = vncInputSelectHead; cur; cur = *nextPtr) {
|
||||
if (cur->client == client) {
|
||||
*nextPtr = cur->next;
|
||||
free(cur);
|
||||
continue;
|
||||
}
|
||||
nextPtr = &cur->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
467
unix/xserver/hw/vnc/vncExtInit.cc
Normal file
467
unix/xserver/hw/vnc/vncExtInit.cc
Normal file
@@ -0,0 +1,467 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include <rfb/Configuration.h>
|
||||
#include <rfb/Logger_stdio.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <rfb/util.h>
|
||||
#include <rfb/ServerCore.h>
|
||||
#include <rdr/HexOutStream.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
#include <rfb/Hostname.h>
|
||||
#include <rfb/Region.h>
|
||||
#include <rfb/ledStates.h>
|
||||
#include <network/TcpSocket.h>
|
||||
#include <network/UnixSocket.h>
|
||||
|
||||
#include "XserverDesktop.h"
|
||||
#include "vncExtInit.h"
|
||||
#include "vncHooks.h"
|
||||
#include "vncBlockHandler.h"
|
||||
#include "vncSelection.h"
|
||||
#include "XorgGlue.h"
|
||||
#include "RandrGlue.h"
|
||||
#include "xorg-version.h"
|
||||
|
||||
extern "C" {
|
||||
void vncSetGlueContext(int screenIndex);
|
||||
}
|
||||
|
||||
using namespace rfb;
|
||||
|
||||
static rfb::LogWriter vlog("vncext");
|
||||
|
||||
// We can't safely get this from Xorg
|
||||
#define MAXSCREENS 16
|
||||
|
||||
static unsigned long vncExtGeneration = 0;
|
||||
static bool initialised = false;
|
||||
static XserverDesktop* desktop[MAXSCREENS] = { 0, };
|
||||
void* vncFbptr[MAXSCREENS] = { 0, };
|
||||
int vncFbstride[MAXSCREENS];
|
||||
|
||||
int vncInetdSock = -1;
|
||||
|
||||
struct CaseInsensitiveCompare {
|
||||
bool operator() (const std::string &a, const std::string &b) const {
|
||||
return strcasecmp(a.c_str(), b.c_str()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::set<std::string, CaseInsensitiveCompare> ParamSet;
|
||||
static ParamSet allowOverrideSet;
|
||||
|
||||
rfb::AliasParameter rfbwait("rfbwait", "Alias for ClientWaitTimeMillis",
|
||||
&rfb::Server::clientWaitTimeMillis);
|
||||
rfb::IntParameter rfbport("rfbport", "TCP port to listen for RFB protocol",0);
|
||||
rfb::StringParameter rfbunixpath("rfbunixpath", "Unix socket to listen for RFB protocol", "");
|
||||
rfb::IntParameter rfbunixmode("rfbunixmode", "Unix socket access mode", 0600);
|
||||
rfb::StringParameter desktopName("desktop", "Name of VNC desktop","x11");
|
||||
rfb::BoolParameter localhostOnly("localhost",
|
||||
"Only allow connections from localhost",
|
||||
false);
|
||||
rfb::BoolParameter noWebsocket("noWebsocket",
|
||||
"Listen on a traditional VNC port instead of websocket",
|
||||
false);
|
||||
rfb::IntParameter websocketPort("websocketPort", "websocket port to listen for", 6800);
|
||||
rfb::StringParameter cert("cert", "SSL pem cert to use for websocket connections", "");
|
||||
rfb::BoolParameter sslonly("sslOnly", "Require SSL for websockets", false);
|
||||
rfb::StringParameter basicauth("BasicAuth", "user:pass for HTTP basic auth for websockets", "");
|
||||
rfb::StringParameter interface("interface",
|
||||
"listen on the specified network address",
|
||||
"all");
|
||||
rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock",
|
||||
"Avoid fake Shift presses for keys affected by NumLock.",
|
||||
true);
|
||||
rfb::StringParameter allowOverride("AllowOverride",
|
||||
"Comma separated list of parameters that can be modified using VNC extension.",
|
||||
"desktop,AcceptPointerEvents,SendCutText,AcceptCutText,SendPrimary,SetPrimary");
|
||||
rfb::BoolParameter setPrimary("SetPrimary", "Set the PRIMARY as well "
|
||||
"as the CLIPBOARD selection", true);
|
||||
rfb::BoolParameter sendPrimary("SendPrimary",
|
||||
"Send the PRIMARY as well as the CLIPBOARD selection",
|
||||
true);
|
||||
|
||||
static PixelFormat vncGetPixelFormat(int scrIdx)
|
||||
{
|
||||
int depth, bpp;
|
||||
int trueColour, bigEndian;
|
||||
int redMask, greenMask, blueMask;
|
||||
|
||||
int redShift, greenShift, blueShift;
|
||||
int redMax, greenMax, blueMax;
|
||||
|
||||
vncGetScreenFormat(scrIdx, &depth, &bpp, &trueColour, &bigEndian,
|
||||
&redMask, &greenMask, &blueMask);
|
||||
|
||||
if (!trueColour) {
|
||||
vlog.error("pseudocolour not supported");
|
||||
abort();
|
||||
}
|
||||
|
||||
redShift = ffs(redMask) - 1;
|
||||
greenShift = ffs(greenMask) - 1;
|
||||
blueShift = ffs(blueMask) - 1;
|
||||
redMax = redMask >> redShift;
|
||||
greenMax = greenMask >> greenShift;
|
||||
blueMax = blueMask >> blueShift;
|
||||
|
||||
return PixelFormat(bpp, depth, bigEndian, trueColour,
|
||||
redMax, greenMax, blueMax,
|
||||
redShift, greenShift, blueShift);
|
||||
}
|
||||
|
||||
static void parseOverrideList(const char *text, ParamSet &out)
|
||||
{
|
||||
for (const char* iter = text; ; ++iter) {
|
||||
if (*iter == ',' || *iter == '\0') {
|
||||
out.insert(std::string(text, iter));
|
||||
text = iter + 1;
|
||||
|
||||
if (*iter == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vncExtensionInit(void)
|
||||
{
|
||||
if (vncExtGeneration == vncGetServerGeneration()) {
|
||||
vlog.error("vncExtensionInit: called twice in same generation?");
|
||||
return;
|
||||
}
|
||||
vncExtGeneration = vncGetServerGeneration();
|
||||
|
||||
if (vncGetScreenCount() > MAXSCREENS)
|
||||
vncFatalError("vncExtensionInit: too many screens");
|
||||
|
||||
if (sizeof(ShortRect) != sizeof(struct UpdateRect))
|
||||
vncFatalError("vncExtensionInit: Incompatible ShortRect size");
|
||||
|
||||
vncAddExtension();
|
||||
|
||||
vncSelectionInit();
|
||||
|
||||
vlog.info("VNC extension running!");
|
||||
|
||||
try {
|
||||
if (!initialised) {
|
||||
rfb::initStdIOLoggers();
|
||||
|
||||
parseOverrideList(allowOverride, allowOverrideSet);
|
||||
allowOverride.setImmutable();
|
||||
|
||||
if (!Server::DLP_ClipLog[0] ||
|
||||
(strcmp(Server::DLP_ClipLog, "off") &&
|
||||
strcmp(Server::DLP_ClipLog, "info") &&
|
||||
strcmp(Server::DLP_ClipLog, "verbose")))
|
||||
vncFatalError("Invalid value to %s", Server::DLP_ClipLog.getName());
|
||||
|
||||
unsigned dummyX, dummyY;
|
||||
if (!Server::maxVideoResolution[0] ||
|
||||
sscanf(Server::maxVideoResolution, "%ux%u", &dummyX, &dummyY) != 2 ||
|
||||
dummyX < 16 ||
|
||||
dummyY < 16)
|
||||
vncFatalError("Invalid value to %s", Server::maxVideoResolution.getName());
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
|
||||
|
||||
if (!desktop[scr]) {
|
||||
std::list<network::SocketListener*> listeners;
|
||||
std::list<network::SocketListener*> httpListeners;
|
||||
if (scr == 0 && vncInetdSock != -1) {
|
||||
if (network::isSocketListening(vncInetdSock))
|
||||
{
|
||||
listeners.push_back(new network::TcpListener(vncInetdSock));
|
||||
vlog.info("inetd wait");
|
||||
}
|
||||
} else if (rfbunixpath.getValueStr()[0] != '\0') {
|
||||
char path[PATH_MAX];
|
||||
int mode = (int)rfbunixmode;
|
||||
|
||||
if (scr == 0)
|
||||
strncpy(path, rfbunixpath, sizeof(path));
|
||||
else
|
||||
snprintf(path, sizeof(path), "%s.%d",
|
||||
rfbunixpath.getValueStr(), scr);
|
||||
path[sizeof(path)-1] = '\0';
|
||||
|
||||
listeners.push_back(new network::UnixListener(path, mode));
|
||||
|
||||
vlog.info("Listening for VNC connections on %s (mode %04o)",
|
||||
path, mode);
|
||||
} else {
|
||||
const char *addr = interface;
|
||||
int port = rfbport;
|
||||
if (port == 0) port = 5900 + atoi(vncGetDisplay());
|
||||
port += 1000 * scr;
|
||||
if (strcasecmp(addr, "all") == 0)
|
||||
addr = 0;
|
||||
if (!noWebsocket)
|
||||
network::createWebsocketListeners(&listeners, websocketPort,
|
||||
localhostOnly ? "local" : addr,
|
||||
sslonly, cert, basicauth, httpDir);
|
||||
else if (localhostOnly)
|
||||
network::createLocalTcpListeners(&listeners, port);
|
||||
else
|
||||
network::createTcpListeners(&listeners, addr, port);
|
||||
|
||||
if (noWebsocket)
|
||||
vlog.info("Listening for VNC connections on %s interface(s), port %d",
|
||||
localhostOnly ? "local" : (const char*)interface,
|
||||
port);
|
||||
else
|
||||
vlog.info("Listening for websocket connections on %s interface(s), port %d",
|
||||
localhostOnly ? "local" : (const char*)interface,
|
||||
(int) websocketPort);
|
||||
}
|
||||
|
||||
CharArray desktopNameStr(desktopName.getData());
|
||||
PixelFormat pf = vncGetPixelFormat(scr);
|
||||
|
||||
vncSetGlueContext(scr);
|
||||
desktop[scr] = new XserverDesktop(scr,
|
||||
listeners,
|
||||
httpListeners,
|
||||
desktopNameStr.buf,
|
||||
pf,
|
||||
vncGetScreenWidth(),
|
||||
vncGetScreenHeight(),
|
||||
vncFbptr[scr],
|
||||
vncFbstride[scr]);
|
||||
vlog.info("created VNC server for screen %d", scr);
|
||||
|
||||
if (scr == 0 && vncInetdSock != -1 && listeners.empty()) {
|
||||
network::Socket* sock = new network::TcpSocket(vncInetdSock);
|
||||
desktop[scr]->addClient(sock, false);
|
||||
vlog.info("added inetd sock");
|
||||
}
|
||||
}
|
||||
|
||||
vncHooksInit(scr);
|
||||
}
|
||||
} catch (rdr::Exception& e) {
|
||||
vncFatalError("vncExtInit: %s",e.str());
|
||||
}
|
||||
|
||||
vncRegisterBlockHandlers();
|
||||
}
|
||||
|
||||
void vncExtensionClose(void)
|
||||
{
|
||||
try {
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
|
||||
delete desktop[scr];
|
||||
desktop[scr] = NULL;
|
||||
}
|
||||
} catch (rdr::Exception& e) {
|
||||
vncFatalError("vncExtInit: %s",e.str());
|
||||
}
|
||||
}
|
||||
|
||||
void vncHandleSocketEvent(int fd, int scrIdx, int read, int write)
|
||||
{
|
||||
desktop[scrIdx]->handleSocketEvent(fd, read, write);
|
||||
}
|
||||
|
||||
void vncCallBlockHandlers(int* timeout)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->blockHandler(timeout);
|
||||
}
|
||||
|
||||
int vncGetAvoidShiftNumLock(void)
|
||||
{
|
||||
return (bool)avoidShiftNumLock;
|
||||
}
|
||||
|
||||
int vncGetSetPrimary(void)
|
||||
{
|
||||
return (bool)setPrimary;
|
||||
}
|
||||
|
||||
int vncGetSendPrimary(void)
|
||||
{
|
||||
return (bool)sendPrimary;
|
||||
}
|
||||
|
||||
void vncUpdateDesktopName(void)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->setDesktopName(desktopName);
|
||||
}
|
||||
|
||||
void vncServerCutText(const char *text, size_t len)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->serverCutText(text, len);
|
||||
}
|
||||
|
||||
int vncConnectClient(const char *addr)
|
||||
{
|
||||
if (strlen(addr) == 0) {
|
||||
try {
|
||||
desktop[0]->disconnectClients();
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("Disconnecting all clients: %s",e.str());
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *host;
|
||||
int port;
|
||||
|
||||
getHostAndPort(addr, &host, &port, 5500);
|
||||
|
||||
try {
|
||||
network::Socket* sock = new network::TcpSocket(host, port);
|
||||
delete [] host;
|
||||
desktop[0]->addClient(sock, true);
|
||||
} catch (rdr::Exception& e) {
|
||||
vlog.error("Reverse connection: %s",e.str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vncGetQueryConnect(uint32_t *opaqueId, const char**username,
|
||||
const char **address, int *timeout)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
|
||||
desktop[scr]->getQueryConnect(opaqueId, username, address, timeout);
|
||||
if (opaqueId != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vncApproveConnection(uint32_t opaqueId, int approve)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++) {
|
||||
desktop[scr]->approveConnection(opaqueId, approve,
|
||||
"Connection rejected by local user");
|
||||
}
|
||||
}
|
||||
|
||||
void vncBell()
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->bell();
|
||||
}
|
||||
|
||||
void vncSetLEDState(unsigned long leds)
|
||||
{
|
||||
unsigned int state;
|
||||
|
||||
state = 0;
|
||||
if (leds & (1 << 0))
|
||||
state |= ledCapsLock;
|
||||
if (leds & (1 << 1))
|
||||
state |= ledNumLock;
|
||||
if (leds & (1 << 2))
|
||||
state |= ledScrollLock;
|
||||
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->setLEDState(state);
|
||||
}
|
||||
|
||||
void vncAddChanged(int scrIdx, const struct UpdateRect *extents,
|
||||
int nRects, const struct UpdateRect *rects)
|
||||
{
|
||||
Region reg;
|
||||
|
||||
reg.setExtentsAndOrderedRects((const ShortRect*)extents,
|
||||
nRects, (const ShortRect*)rects);
|
||||
desktop[scrIdx]->add_changed(reg);
|
||||
}
|
||||
|
||||
void vncAddCopied(int scrIdx, const struct UpdateRect *extents,
|
||||
int nRects, const struct UpdateRect *rects,
|
||||
int dx, int dy)
|
||||
{
|
||||
Region reg;
|
||||
|
||||
reg.setExtentsAndOrderedRects((const ShortRect*)extents,
|
||||
nRects, (const ShortRect*)rects);
|
||||
desktop[scrIdx]->add_copied(reg, rfb::Point(dx, dy));
|
||||
}
|
||||
|
||||
void vncSetCursor(int width, int height, int hotX, int hotY,
|
||||
const unsigned char *rgbaData)
|
||||
{
|
||||
for (int scr = 0; scr < vncGetScreenCount(); scr++)
|
||||
desktop[scr]->setCursor(width, height, hotX, hotY, rgbaData);
|
||||
}
|
||||
|
||||
void vncPreScreenResize(int scrIdx)
|
||||
{
|
||||
// We need to prevent the RFB core from accessing the framebuffer
|
||||
// for a while as there might be updates thrown our way inside
|
||||
// the routines that change the screen (i.e. before we have a
|
||||
// pointer to the new framebuffer).
|
||||
desktop[scrIdx]->blockUpdates();
|
||||
}
|
||||
|
||||
void vncPostScreenResize(int scrIdx, int success, int width, int height)
|
||||
{
|
||||
if (success) {
|
||||
// Let the RFB core know of the new dimensions and framebuffer
|
||||
desktop[scrIdx]->setFramebuffer(width, height,
|
||||
vncFbptr[scrIdx], vncFbstride[scrIdx]);
|
||||
}
|
||||
|
||||
desktop[scrIdx]->unblockUpdates();
|
||||
|
||||
if (success) {
|
||||
// Mark entire screen as changed
|
||||
desktop[scrIdx]->add_changed(Region(Rect(0, 0, width, height)));
|
||||
}
|
||||
}
|
||||
|
||||
void vncRefreshScreenLayout(int scrIdx)
|
||||
{
|
||||
try {
|
||||
desktop[scrIdx]->refreshScreenLayout();
|
||||
} catch (rdr::Exception& e) {
|
||||
vncFatalError("%s", e.str());
|
||||
}
|
||||
}
|
||||
|
||||
int vncOverrideParam(const char *nameAndValue)
|
||||
{
|
||||
const char* equalSign = strchr(nameAndValue, '=');
|
||||
if (!equalSign)
|
||||
return 0;
|
||||
|
||||
std::string key(nameAndValue, equalSign);
|
||||
if (allowOverrideSet.find(key) == allowOverrideSet.end())
|
||||
return 0;
|
||||
|
||||
return rfb::Configuration::setParam(nameAndValue);
|
||||
}
|
||||
100
unix/xserver/hw/vnc/vncExtInit.h
Normal file
100
unix/xserver/hw/vnc/vncExtInit.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2011-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#ifndef __VNCEXTINIT_H__
|
||||
#define __VNCEXTINIT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
// Only from C++
|
||||
#ifdef __cplusplus
|
||||
namespace rfb { class StringParameter; };
|
||||
|
||||
extern rfb::StringParameter httpDir;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// vncExt.c
|
||||
extern int vncNoClipboard;
|
||||
|
||||
void vncAddExtension(void);
|
||||
|
||||
int vncNotifyQueryConnect(void);
|
||||
|
||||
// vncExtInit.cc
|
||||
extern void* vncFbptr[];
|
||||
extern int vncFbstride[];
|
||||
|
||||
extern int vncInetdSock;
|
||||
|
||||
void vncExtensionInit(void);
|
||||
void vncExtensionClose(void);
|
||||
|
||||
void vncHandleSocketEvent(int fd, int scrIdx, int read, int write);
|
||||
void vncCallBlockHandlers(int* timeout);
|
||||
|
||||
int vncGetAvoidShiftNumLock(void);
|
||||
|
||||
int vncGetSetPrimary(void);
|
||||
int vncGetSendPrimary(void);
|
||||
|
||||
void vncUpdateDesktopName(void);
|
||||
|
||||
void vncServerCutText(const char *text, size_t len);
|
||||
|
||||
int vncConnectClient(const char *addr);
|
||||
|
||||
void vncGetQueryConnect(uint32_t *opaqueId, const char**username,
|
||||
const char **address, int *timeout);
|
||||
void vncApproveConnection(uint32_t opaqueId, int approve);
|
||||
|
||||
void vncBell(void);
|
||||
|
||||
void vncSetLEDState(unsigned long leds);
|
||||
|
||||
// Must match rfb::ShortRect in common/rfb/Region.h, and BoxRec in the
|
||||
// Xorg source.
|
||||
struct UpdateRect {
|
||||
short x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
void vncAddChanged(int scrIdx, const struct UpdateRect *extents,
|
||||
int nRects, const struct UpdateRect *rects);
|
||||
void vncAddCopied(int scrIdx, const struct UpdateRect *extents,
|
||||
int nRects, const struct UpdateRect *rects,
|
||||
int dx, int dy);
|
||||
|
||||
void vncSetCursor(int width, int height, int hotX, int hotY,
|
||||
const unsigned char *rgbaData);
|
||||
|
||||
void vncPreScreenResize(int scrIdx);
|
||||
void vncPostScreenResize(int scrIdx, int success, int width, int height);
|
||||
void vncRefreshScreenLayout(int scrIdx);
|
||||
|
||||
int vncOverrideParam(const char *nameAndValue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2432
unix/xserver/hw/vnc/vncHooks.c
Normal file
2432
unix/xserver/hw/vnc/vncHooks.c
Normal file
File diff suppressed because it is too large
Load Diff
35
unix/xserver/hw/vnc/vncHooks.h
Normal file
35
unix/xserver/hw/vnc/vncHooks.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2009-2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#ifndef __VNCHOOKS_H__
|
||||
#define __VNCHOOKS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int vncHooksInit(int scrIdx);
|
||||
|
||||
void vncGetScreenImage(int scrIdx, int x, int y, int width, int height,
|
||||
char *buffer, int strideBytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
140
unix/xserver/hw/vnc/vncModule.c
Normal file
140
unix/xserver/hw/vnc/vncModule.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2015 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
/* This is the xf86 module code for the vnc extension.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "opaque.h"
|
||||
#include "randrstr.h"
|
||||
|
||||
#include "xorg-version.h"
|
||||
#if XORG <= 111
|
||||
typedef pointer XF86OptionPtr;
|
||||
#endif
|
||||
|
||||
#include "xf86.h"
|
||||
#include "xf86Module.h"
|
||||
|
||||
#include "vncExtInit.h"
|
||||
#include "RFBGlue.h"
|
||||
#include "XorgGlue.h"
|
||||
#include "RandrGlue.h"
|
||||
|
||||
static void vncModuleInit(INITARGS);
|
||||
|
||||
static MODULESETUPPROTO(vncSetup);
|
||||
|
||||
ExtensionModule vncExt =
|
||||
{
|
||||
vncModuleInit,
|
||||
"VNC",
|
||||
#if XORG < 112
|
||||
NULL,
|
||||
NULL,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static XF86ModuleVersionInfo vncVersRec =
|
||||
{
|
||||
"vnc",
|
||||
"KasmVNC Project",
|
||||
MODINFOSTRING1,
|
||||
MODINFOSTRING2,
|
||||
XORG_VERSION_CURRENT,
|
||||
1, 0, 0,
|
||||
ABI_CLASS_EXTENSION, /* needs the server extension ABI */
|
||||
ABI_EXTENSION_VERSION,
|
||||
MOD_CLASS_EXTENSION,
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
_X_EXPORT XF86ModuleData vncModuleData = { &vncVersRec, vncSetup, NULL };
|
||||
|
||||
static void *
|
||||
vncSetup(void * module, void * opts, int *errmaj, int *errmin) {
|
||||
#if XORG >= 116
|
||||
LoadExtensionList(&vncExt, 1, FALSE);
|
||||
#else
|
||||
LoadExtension(&vncExt, FALSE);
|
||||
#endif
|
||||
/* Need a non-NULL return value to indicate success */
|
||||
return (void *)1;
|
||||
}
|
||||
|
||||
static void vncModuleInit(INITARGS)
|
||||
{
|
||||
static char once = 0;
|
||||
|
||||
if (!once) {
|
||||
once++;
|
||||
|
||||
vncInitRFB();
|
||||
|
||||
for (int scr = 0; scr < screenInfo.numScreens; scr++) {
|
||||
ScrnInfoPtr pScrn;
|
||||
XF86OptionPtr option;
|
||||
|
||||
pScrn = xf86Screens[scr];
|
||||
option = pScrn->options;
|
||||
while (option != NULL) {
|
||||
vncSetParam(xf86OptionName(option), xf86OptionValue(option));
|
||||
option = xf86NextOption(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vncExtensionInit();
|
||||
}
|
||||
|
||||
void vncClientGone(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
int vncRandRCanCreateScreenOutputs(int scrIdx, int extraOutputs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRCreateScreenOutputs(int scrIdx, int extraOutputs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vncRandRCanCreateModes(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* vncRandRCreateMode(void* output, int width, int height)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* vncRandRSetPreferredMode(void* output, void* mode)
|
||||
{
|
||||
/*
|
||||
* We're not going to change which modes are preferred,
|
||||
* so just return the incoming mode.
|
||||
*/
|
||||
return mode;
|
||||
}
|
||||
524
unix/xserver/hw/vnc/vncSelection.c
Normal file
524
unix/xserver/hw/vnc/vncSelection.c
Normal file
@@ -0,0 +1,524 @@
|
||||
/* Copyright 2016 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "propertyst.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "selection.h"
|
||||
#include "windowstr.h"
|
||||
#include "xace.h"
|
||||
|
||||
#include "xorg-version.h"
|
||||
|
||||
#include "vncExtInit.h"
|
||||
#include "vncSelection.h"
|
||||
#include "RFBGlue.h"
|
||||
|
||||
#define LOG_NAME "Selection"
|
||||
|
||||
#define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)
|
||||
|
||||
static Atom xaPRIMARY, xaCLIPBOARD;
|
||||
static Atom xaTARGETS, xaTIMESTAMP, xaSTRING, xaTEXT, xaUTF8_STRING;
|
||||
|
||||
static WindowPtr pWindow;
|
||||
static Window wid;
|
||||
|
||||
static char* clientCutText;
|
||||
static int clientCutTextLen;
|
||||
|
||||
static int vncCreateSelectionWindow(void);
|
||||
static int vncOwnSelection(Atom selection);
|
||||
static int vncProcConvertSelection(ClientPtr client);
|
||||
static int vncProcSendEvent(ClientPtr client);
|
||||
static void vncSelectionCallback(CallbackListPtr *callbacks,
|
||||
void * data, void * args);
|
||||
|
||||
static int (*origProcConvertSelection)(ClientPtr);
|
||||
static int (*origProcSendEvent)(ClientPtr);
|
||||
|
||||
void vncSelectionInit(void)
|
||||
{
|
||||
xaPRIMARY = MakeAtom("PRIMARY", 7, TRUE);
|
||||
xaCLIPBOARD = MakeAtom("CLIPBOARD", 9, TRUE);
|
||||
|
||||
xaTARGETS = MakeAtom("TARGETS", 7, TRUE);
|
||||
xaTIMESTAMP = MakeAtom("TIMESTAMP", 9, TRUE);
|
||||
xaSTRING = MakeAtom("STRING", 6, TRUE);
|
||||
xaTEXT = MakeAtom("TEXT", 4, TRUE);
|
||||
xaUTF8_STRING = MakeAtom("UTF8_STRING", 11, TRUE);
|
||||
|
||||
/* There are no hooks for when these are internal windows, so
|
||||
* override the relevant handlers. */
|
||||
origProcConvertSelection = ProcVector[X_ConvertSelection];
|
||||
ProcVector[X_ConvertSelection] = vncProcConvertSelection;
|
||||
origProcSendEvent = ProcVector[X_SendEvent];
|
||||
ProcVector[X_SendEvent] = vncProcSendEvent;
|
||||
|
||||
if (!AddCallback(&SelectionCallback, vncSelectionCallback, 0))
|
||||
FatalError("Add VNC SelectionCallback failed\n");
|
||||
}
|
||||
|
||||
void vncClientCutText(const char* str, int len)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (clientCutText != NULL)
|
||||
free(clientCutText);
|
||||
|
||||
clientCutText = malloc(len);
|
||||
if (clientCutText == NULL) {
|
||||
LOG_ERROR("Could not allocate clipboard buffer");
|
||||
DeleteWindowFromAnySelections(pWindow);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(clientCutText, str, len);
|
||||
clientCutTextLen = len;
|
||||
|
||||
if (vncGetSetPrimary()) {
|
||||
rc = vncOwnSelection(xaPRIMARY);
|
||||
if (rc != Success)
|
||||
LOG_ERROR("Could not set PRIMARY selection");
|
||||
}
|
||||
|
||||
vncOwnSelection(xaCLIPBOARD);
|
||||
if (rc != Success)
|
||||
LOG_ERROR("Could not set CLIPBOARD selection");
|
||||
}
|
||||
|
||||
static int vncCreateSelectionWindow(void)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
int result;
|
||||
|
||||
if (pWindow != NULL)
|
||||
return Success;
|
||||
|
||||
pScreen = screenInfo.screens[0];
|
||||
|
||||
wid = FakeClientID(0);
|
||||
pWindow = CreateWindow(wid, pScreen->root,
|
||||
0, 0, 100, 100, 0, InputOnly,
|
||||
0, NULL, 0, serverClient,
|
||||
CopyFromParent, &result);
|
||||
if (!pWindow)
|
||||
return result;
|
||||
|
||||
if (!AddResource(pWindow->drawable.id, RT_WINDOW, pWindow))
|
||||
return BadAlloc;
|
||||
|
||||
LOG_DEBUG("Created selection window");
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int vncOwnSelection(Atom selection)
|
||||
{
|
||||
Selection *pSel;
|
||||
int rc;
|
||||
|
||||
SelectionInfoRec info;
|
||||
|
||||
rc = vncCreateSelectionWindow();
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
rc = dixLookupSelection(&pSel, selection, serverClient, DixSetAttrAccess);
|
||||
if (rc == Success) {
|
||||
if (pSel->client && (pSel->client != serverClient)) {
|
||||
xEvent event = {
|
||||
.u.selectionClear.time = currentTime.milliseconds,
|
||||
.u.selectionClear.window = pSel->window,
|
||||
.u.selectionClear.atom = pSel->selection
|
||||
};
|
||||
event.u.u.type = SelectionClear;
|
||||
WriteEventsToClient(pSel->client, 1, &event);
|
||||
}
|
||||
} else if (rc == BadMatch) {
|
||||
pSel = dixAllocateObjectWithPrivates(Selection, PRIVATE_SELECTION);
|
||||
if (!pSel)
|
||||
return BadAlloc;
|
||||
|
||||
pSel->selection = selection;
|
||||
|
||||
rc = XaceHookSelectionAccess(serverClient, &pSel,
|
||||
DixCreateAccess | DixSetAttrAccess);
|
||||
if (rc != Success) {
|
||||
free(pSel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
pSel->next = CurrentSelections;
|
||||
CurrentSelections = pSel;
|
||||
}
|
||||
else
|
||||
return rc;
|
||||
|
||||
pSel->lastTimeChanged = currentTime;
|
||||
pSel->window = wid;
|
||||
pSel->pWin = pWindow;
|
||||
pSel->client = serverClient;
|
||||
|
||||
LOG_DEBUG("Grabbed %s selection", NameForAtom(selection));
|
||||
|
||||
info.selection = pSel;
|
||||
info.client = serverClient;
|
||||
info.kind = SelectionSetOwner;
|
||||
CallCallbacks(&SelectionCallback, &info);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int vncConvertSelection(ClientPtr client, Atom selection,
|
||||
Atom target, Atom property,
|
||||
Window requestor, CARD32 time)
|
||||
{
|
||||
Selection *pSel;
|
||||
WindowPtr pWin;
|
||||
int rc;
|
||||
|
||||
Atom realProperty;
|
||||
|
||||
xEvent event;
|
||||
|
||||
LOG_DEBUG("Selection request for %s (type %s)",
|
||||
NameForAtom(selection), NameForAtom(target));
|
||||
|
||||
rc = dixLookupSelection(&pSel, selection, client, DixGetAttrAccess);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
/* We do not validate the time argument because neither does
|
||||
* dix/selection.c and some clients (e.g. Qt) relies on this */
|
||||
|
||||
rc = dixLookupWindow(&pWin, requestor, client, DixSetAttrAccess);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
if (property != None)
|
||||
realProperty = property;
|
||||
else
|
||||
realProperty = target;
|
||||
|
||||
/* FIXME: MULTIPLE target */
|
||||
|
||||
if (target == xaTARGETS) {
|
||||
Atom targets[] = { xaTARGETS, xaTIMESTAMP,
|
||||
xaSTRING, xaTEXT, xaUTF8_STRING };
|
||||
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_ATOM, 32, PropModeReplace,
|
||||
sizeof(targets)/sizeof(targets[0]),
|
||||
targets, TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if (target == xaTIMESTAMP) {
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_INTEGER, 32, PropModeReplace, 1,
|
||||
&pSel->lastTimeChanged.milliseconds,
|
||||
TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if ((target == xaSTRING) || (target == xaTEXT)) {
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
XA_STRING, 8, PropModeReplace,
|
||||
clientCutTextLen, clientCutText,
|
||||
TRUE);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else if (target == xaUTF8_STRING) {
|
||||
unsigned char* buffer;
|
||||
unsigned char* out;
|
||||
size_t len;
|
||||
|
||||
const unsigned char* in;
|
||||
size_t in_len;
|
||||
|
||||
buffer = malloc(clientCutTextLen*2);
|
||||
if (buffer == NULL)
|
||||
return BadAlloc;
|
||||
|
||||
out = buffer;
|
||||
len = 0;
|
||||
in = clientCutText;
|
||||
in_len = clientCutTextLen;
|
||||
while (in_len > 0) {
|
||||
if (*in & 0x80) {
|
||||
*out++ = 0xc0 | (*in >> 6);
|
||||
*out++ = 0x80 | (*in & 0x3f);
|
||||
len += 2;
|
||||
in++;
|
||||
in_len--;
|
||||
} else {
|
||||
*out++ = *in++;
|
||||
len++;
|
||||
in_len--;
|
||||
}
|
||||
}
|
||||
|
||||
rc = dixChangeWindowProperty(serverClient, pWin, realProperty,
|
||||
xaUTF8_STRING, 8, PropModeReplace,
|
||||
len, buffer, TRUE);
|
||||
free(buffer);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
} else {
|
||||
return BadMatch;
|
||||
}
|
||||
|
||||
event.u.u.type = SelectionNotify;
|
||||
event.u.selectionNotify.time = time;
|
||||
event.u.selectionNotify.requestor = requestor;
|
||||
event.u.selectionNotify.selection = selection;
|
||||
event.u.selectionNotify.target = target;
|
||||
event.u.selectionNotify.property = property;
|
||||
WriteEventsToClient(client, 1, &event);
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int vncProcConvertSelection(ClientPtr client)
|
||||
{
|
||||
Bool paramsOkay;
|
||||
WindowPtr pWin;
|
||||
Selection *pSel;
|
||||
int rc;
|
||||
|
||||
REQUEST(xConvertSelectionReq);
|
||||
REQUEST_SIZE_MATCH(xConvertSelectionReq);
|
||||
|
||||
rc = dixLookupWindow(&pWin, stuff->requestor, client, DixSetAttrAccess);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
paramsOkay = ValidAtom(stuff->selection) && ValidAtom(stuff->target);
|
||||
paramsOkay &= (stuff->property == None) || ValidAtom(stuff->property);
|
||||
if (!paramsOkay) {
|
||||
client->errorValue = stuff->property;
|
||||
return BadAtom;
|
||||
}
|
||||
|
||||
rc = dixLookupSelection(&pSel, stuff->selection, client, DixReadAccess);
|
||||
if (rc == Success && pSel->client == serverClient &&
|
||||
pSel->window == wid) {
|
||||
rc = vncConvertSelection(client, stuff->selection,
|
||||
stuff->target, stuff->property,
|
||||
stuff->requestor, stuff->time);
|
||||
if (rc != Success) {
|
||||
xEvent event;
|
||||
|
||||
memset(&event, 0, sizeof(xEvent));
|
||||
event.u.u.type = SelectionNotify;
|
||||
event.u.selectionNotify.time = stuff->time;
|
||||
event.u.selectionNotify.requestor = stuff->requestor;
|
||||
event.u.selectionNotify.selection = stuff->selection;
|
||||
event.u.selectionNotify.target = stuff->target;
|
||||
event.u.selectionNotify.property = None;
|
||||
WriteEventsToClient(client, 1, &event);
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
return origProcConvertSelection(client);
|
||||
}
|
||||
|
||||
static void vncSelectionRequest(Atom selection, Atom target)
|
||||
{
|
||||
Selection *pSel;
|
||||
xEvent event;
|
||||
int rc;
|
||||
|
||||
rc = vncCreateSelectionWindow();
|
||||
if (rc != Success)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Requesting %s for %s selection",
|
||||
NameForAtom(target), NameForAtom(selection));
|
||||
|
||||
rc = dixLookupSelection(&pSel, selection, serverClient, DixGetAttrAccess);
|
||||
if (rc != Success)
|
||||
return;
|
||||
|
||||
event.u.u.type = SelectionRequest;
|
||||
event.u.selectionRequest.owner = pSel->window;
|
||||
event.u.selectionRequest.time = currentTime.milliseconds;
|
||||
event.u.selectionRequest.requestor = wid;
|
||||
event.u.selectionRequest.selection = selection;
|
||||
event.u.selectionRequest.target = target;
|
||||
event.u.selectionRequest.property = target;
|
||||
WriteEventsToClient(pSel->client, 1, &event);
|
||||
}
|
||||
|
||||
static Bool vncHasAtom(Atom atom, const Atom list[], size_t size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0;i < size;i++) {
|
||||
if (list[i] == atom)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void vncHandleSelection(Atom selection, Atom target,
|
||||
Atom property, Atom requestor,
|
||||
TimeStamp time)
|
||||
{
|
||||
PropertyPtr prop;
|
||||
int rc;
|
||||
|
||||
rc = dixLookupProperty(&prop, pWindow, property,
|
||||
serverClient, DixReadAccess);
|
||||
if (rc != Success)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Selection notification for %s (target %s, property %s, type %s)",
|
||||
NameForAtom(selection), NameForAtom(target),
|
||||
NameForAtom(property), NameForAtom(prop->type));
|
||||
|
||||
if (target != property)
|
||||
return;
|
||||
|
||||
if (target == xaTARGETS) {
|
||||
if (prop->format != 32)
|
||||
return;
|
||||
if (prop->type != XA_ATOM)
|
||||
return;
|
||||
|
||||
if (vncHasAtom(xaSTRING, (const Atom*)prop->data, prop->size))
|
||||
vncSelectionRequest(selection, xaSTRING);
|
||||
else if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
|
||||
vncSelectionRequest(selection, xaUTF8_STRING);
|
||||
} else if (target == xaSTRING) {
|
||||
if (prop->format != 8)
|
||||
return;
|
||||
if (prop->type != xaSTRING)
|
||||
return;
|
||||
|
||||
vncServerCutText(prop->data, prop->size);
|
||||
} else if (target == xaUTF8_STRING) {
|
||||
unsigned char* buffer;
|
||||
unsigned char* out;
|
||||
size_t len;
|
||||
|
||||
const unsigned char* in;
|
||||
size_t in_len;
|
||||
|
||||
if (prop->format != 8)
|
||||
return;
|
||||
if (prop->type != xaUTF8_STRING)
|
||||
return;
|
||||
|
||||
buffer = malloc(prop->size);
|
||||
if (buffer == NULL)
|
||||
return;
|
||||
|
||||
out = buffer;
|
||||
len = 0;
|
||||
in = prop->data;
|
||||
in_len = prop->size;
|
||||
while (in_len > 0) {
|
||||
if ((*in & 0x80) == 0x00) {
|
||||
*out++ = *in++;
|
||||
len++;
|
||||
in_len--;
|
||||
} else if ((*in & 0xe0) == 0xc0) {
|
||||
unsigned ucs;
|
||||
ucs = (*in++ & 0x1f) << 6;
|
||||
in_len--;
|
||||
if (in_len > 0) {
|
||||
ucs |= (*in++ & 0x3f);
|
||||
in_len--;
|
||||
}
|
||||
if (ucs <= 0xff)
|
||||
*out++ = ucs;
|
||||
else
|
||||
*out++ = '?';
|
||||
len++;
|
||||
} else {
|
||||
*out++ = '?';
|
||||
len++;
|
||||
do {
|
||||
in++;
|
||||
in_len--;
|
||||
} while ((in_len > 0) && ((*in & 0xc0) == 0x80));
|
||||
}
|
||||
}
|
||||
|
||||
vncServerCutText((const char*)buffer, len);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
#define SEND_EVENT_BIT 0x80
|
||||
|
||||
static int vncProcSendEvent(ClientPtr client)
|
||||
{
|
||||
REQUEST(xSendEventReq);
|
||||
REQUEST_SIZE_MATCH(xSendEventReq);
|
||||
|
||||
stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
|
||||
|
||||
if (stuff->event.u.u.type == SelectionNotify &&
|
||||
stuff->event.u.selectionNotify.requestor == wid) {
|
||||
TimeStamp time;
|
||||
time = ClientTimeToServerTime(stuff->event.u.selectionNotify.time);
|
||||
vncHandleSelection(stuff->event.u.selectionNotify.selection,
|
||||
stuff->event.u.selectionNotify.target,
|
||||
stuff->event.u.selectionNotify.property,
|
||||
stuff->event.u.selectionNotify.requestor,
|
||||
time);
|
||||
}
|
||||
|
||||
return origProcSendEvent(client);
|
||||
}
|
||||
|
||||
static void vncSelectionCallback(CallbackListPtr *callbacks,
|
||||
void * data, void * args)
|
||||
{
|
||||
SelectionInfoRec *info = (SelectionInfoRec *) args;
|
||||
|
||||
if (info->kind != SelectionSetOwner)
|
||||
return;
|
||||
if (info->client == serverClient)
|
||||
return;
|
||||
|
||||
LOG_DEBUG("Selection owner change for %s",
|
||||
NameForAtom(info->selection->selection));
|
||||
|
||||
if ((info->selection->selection != xaPRIMARY) &&
|
||||
(info->selection->selection != xaCLIPBOARD))
|
||||
return;
|
||||
|
||||
if ((info->selection->selection == xaPRIMARY) &&
|
||||
!vncGetSendPrimary())
|
||||
return;
|
||||
|
||||
vncSelectionRequest(info->selection->selection, xaTARGETS);
|
||||
}
|
||||
33
unix/xserver/hw/vnc/vncSelection.h
Normal file
33
unix/xserver/hw/vnc/vncSelection.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2016 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
#ifndef __SELECTION_H__
|
||||
#define __SELECTION_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void vncSelectionInit(void);
|
||||
|
||||
void vncClientCutText(const char* str, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
unix/xserver/hw/vnc/xorg-version.h
Normal file
61
unix/xserver/hw/vnc/xorg-version.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* Copyright (C) 2009 TightVNC Team
|
||||
* Copyright (C) 2009 Red Hat, Inc.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#ifndef XORG_VERSION_H
|
||||
#define XORG_VERSION_H
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#if XORG_VERSION_CURRENT < ((1 * 10000000) + (6 * 100000) + (99 * 1000))
|
||||
#error "X.Org older than 1.7 is not supported"
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (7 * 100000) + (99 * 1000))
|
||||
#define XORG 17
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (8 * 100000) + (99 * 1000))
|
||||
#define XORG 18
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (9 * 100000) + (99 * 1000))
|
||||
#define XORG 19
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (10 * 100000) + (99 * 1000))
|
||||
#define XORG 110
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (11 * 100000) + (99 * 1000))
|
||||
#define XORG 111
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (12 * 100000) + (99 * 1000))
|
||||
#define XORG 112
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (13 * 100000) + (99 * 1000))
|
||||
#define XORG 113
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (14 * 100000) + (99 * 1000))
|
||||
#define XORG 114
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (15 * 100000) + (99 * 1000))
|
||||
#define XORG 115
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (16 * 100000) + (99 * 1000))
|
||||
#define XORG 116
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (17 * 100000) + (99 * 1000))
|
||||
#define XORG 117
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (18 * 100000) + (99 * 1000))
|
||||
#define XORG 118
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (19 * 100000) + (99 * 1000))
|
||||
#define XORG 119
|
||||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (20 * 100000) + (99 * 1000))
|
||||
#define XORG 120
|
||||
#else
|
||||
#error "X.Org newer than 1.20 is not supported"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1854
unix/xserver/hw/vnc/xvnc.c
Normal file
1854
unix/xserver/hw/vnc/xvnc.c
Normal file
File diff suppressed because it is too large
Load Diff
91
unix/xserver110.patch
Normal file
91
unix/xserver110.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2011-05-11 11:19:24.410708163 +0200
|
||||
+++ xserver/configure.ac 2011-05-11 11:19:26.409635824 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.10.1.901, [http
|
||||
RELEASE_DATE="2011-05-06"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros minimum of 1.10 for XORG_CHECK_SGML_DOCTOOLS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -65,6 +64,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1513,6 +1513,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1551,6 +1555,8 @@ xorg_bus_linuxpci=no
|
||||
xorg_bus_bsdpci=no
|
||||
xorg_bus_sparc=no
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1797,7 +1803,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2259,6 +2264,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2011-05-11 11:19:24.476705776 +0200
|
||||
+++ xserver/hw/Makefile.am 2011-05-11 11:19:26.409635824 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2011-05-11 11:19:24.549703133 +0200
|
||||
+++ xserver/mi/miinitext.c 2011-05-11 11:19:42.022070885 +0200
|
||||
@@ -263,6 +263,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -433,6 +436,9 @@ InitExtensions(int argc, char *argv[])
|
||||
#ifdef XF86BIGFONT
|
||||
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension) XFree86VidModeExtensionInit();
|
||||
91
unix/xserver111.patch
Normal file
91
unix/xserver111.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2012-08-28 14:08:11.523694314 +0200
|
||||
+++ xserver/configure.ac 2012-08-28 14:08:59.122696574 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.11.4, [https://
|
||||
RELEASE_DATE="2012-01-27"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros minimum of 1.14 for XORG_COMPILER_BRAND in XORG_DEFAULT_OPTIONS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -72,6 +71,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1476,6 +1476,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1514,6 +1518,8 @@ xorg_bus_linuxpci=no
|
||||
xorg_bus_bsdpci=no
|
||||
xorg_bus_sparc=no
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1750,7 +1756,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2217,6 +2222,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2012-08-28 14:08:12.554694327 +0200
|
||||
+++ xserver/hw/Makefile.am 2012-08-28 14:08:59.123696574 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2012-08-28 14:08:13.063694337 +0200
|
||||
+++ xserver/mi/miinitext.c 2012-08-28 14:08:59.123696574 +0200
|
||||
@@ -263,6 +263,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -433,6 +436,9 @@ InitExtensions(int argc, char *argv[])
|
||||
#ifdef XF86BIGFONT
|
||||
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension) XFree86VidModeExtensionInit();
|
||||
91
unix/xserver112.patch
Normal file
91
unix/xserver112.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2012-08-28 15:01:35.142325880 +0200
|
||||
+++ xserver/configure.ac 2012-08-28 15:02:06.292300682 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.12.4, [https://
|
||||
RELEASE_DATE="2012-08-27"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros minimum of 1.14 for XORG_COMPILER_BRAND in XORG_DEFAULT_OPTIONS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -72,6 +71,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1493,6 +1493,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1527,6 +1531,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1743,7 +1749,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2209,6 +2214,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2012-08-28 15:01:35.225325813 +0200
|
||||
+++ xserver/hw/Makefile.am 2012-08-28 15:02:06.292300682 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2012-08-28 15:01:35.311325743 +0200
|
||||
+++ xserver/mi/miinitext.c 2012-08-28 15:02:06.293300681 +0200
|
||||
@@ -266,6 +266,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -449,6 +452,9 @@ InitExtensions(int argc, char *argv[])
|
||||
if (!noXFree86BigfontExtension)
|
||||
XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension)
|
||||
92
unix/xserver113.patch
Normal file
92
unix/xserver113.patch
Normal file
@@ -0,0 +1,92 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2012-08-28 15:35:23.778810954 +0200
|
||||
+++ xserver/configure.ac 2012-08-28 15:54:46.396743431 +0200
|
||||
@@ -31,7 +31,6 @@ RELEASE_DATE="2012-08-21"
|
||||
RELEASE_NAME="Splashing Orca"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros minimum of 1.14 for XORG_COMPILER_BRAND in XORG_DEFAULT_OPTIONS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -73,6 +72,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1561,6 +1561,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1596,6 +1600,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1815,7 +1821,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2280,6 +2285,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2012-08-28 15:35:23.856810890 +0200
|
||||
+++ xserver/hw/Makefile.am 2012-08-28 15:35:42.272795917 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2012-08-28 15:35:23.000000000 +0200
|
||||
+++ xserver/mi/miinitext.c 2012-09-05 15:07:40.714953972 +0200
|
||||
@@ -112,6 +112,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -238,6 +242,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
137
unix/xserver114.patch
Normal file
137
unix/xserver114.patch
Normal file
@@ -0,0 +1,137 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2013-04-09 16:35:38.000000000 +0200
|
||||
+++ xserver/configure.ac 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -72,6 +72,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1573,6 +1574,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1608,6 +1613,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1827,7 +1834,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2292,6 +2298,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2013-04-09 16:36:46.000000000 +0200
|
||||
+++ xserver/hw/Makefile.am 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2013-04-09 16:37:21.000000000 +0200
|
||||
+++ xserver/mi/miinitext.c 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -112,6 +112,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -238,6 +242,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
diff -up xserver/os/WaitFor.c.vnc xserver/os/WaitFor.c
|
||||
--- xserver/os/WaitFor.c.vnc 2013-04-10 14:51:13.000000000 +0200
|
||||
+++ xserver/os/WaitFor.c 2013-04-10 14:55:40.000000000 +0200
|
||||
@@ -124,6 +124,9 @@ static void DoTimer(OsTimerPtr timer, CA
|
||||
static void CheckAllTimers(void);
|
||||
static OsTimerPtr timers = NULL;
|
||||
|
||||
+extern void vncWriteBlockHandler(fd_set *fds);
|
||||
+extern void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
+
|
||||
/*****************
|
||||
* WaitForSomething:
|
||||
* Make the server suspend until there is
|
||||
@@ -149,6 +152,7 @@ WaitForSomething(int *pClientsReady)
|
||||
INT32 timeout = 0;
|
||||
fd_set clientsReadable;
|
||||
fd_set clientsWritable;
|
||||
+ fd_set socketsWritable;
|
||||
int curclient;
|
||||
int selecterr;
|
||||
static int nready;
|
||||
@@ -207,6 +211,9 @@ WaitForSomething(int *pClientsReady)
|
||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
||||
}
|
||||
|
||||
+ FD_ZERO(&socketsWritable);
|
||||
+ vncWriteBlockHandler(&socketsWritable);
|
||||
+
|
||||
BlockHandler((pointer) &wt, (pointer) &LastSelectMask);
|
||||
if (NewOutputPending)
|
||||
FlushAllOutput();
|
||||
@@ -218,10 +225,20 @@ WaitForSomething(int *pClientsReady)
|
||||
i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
|
||||
}
|
||||
else {
|
||||
- i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ORSET(&socketsWritable, &ClientsWriteBlocked, &socketsWritable);
|
||||
+
|
||||
+ if (XFD_ANYSET(&socketsWritable)) {
|
||||
+ i = Select (MaxClients, &LastSelectMask, &socketsWritable, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ANDSET(&clientsWritable, &socketsWritable, &ClientsWriteBlocked);
|
||||
+ } else {
|
||||
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ }
|
||||
}
|
||||
selecterr = GetErrno();
|
||||
WakeupHandler(i, (pointer) &LastSelectMask);
|
||||
+ vncWriteWakeupHandler(i, &socketsWritable);
|
||||
if (i <= 0) { /* An error or timeout occurred */
|
||||
if (dispatchException)
|
||||
return 0;
|
||||
137
unix/xserver115.patch
Normal file
137
unix/xserver115.patch
Normal file
@@ -0,0 +1,137 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2013-04-09 16:35:38.000000000 +0200
|
||||
+++ xserver/configure.ac 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -72,6 +72,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_LIBTOOL_WIN32_DLL
|
||||
AC_DISABLE_STATIC
|
||||
@@ -1573,6 +1573,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1608,6 +1612,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1827,7 +1833,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2292,6 +2297,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2013-04-09 16:36:46.000000000 +0200
|
||||
+++ xserver/hw/Makefile.am 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2013-04-09 16:37:21.000000000 +0200
|
||||
+++ xserver/mi/miinitext.c 2013-04-09 18:16:31.000000000 +0200
|
||||
@@ -112,6 +112,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -238,6 +242,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
diff -up xserver/os/WaitFor.c.vnc xserver/os/WaitFor.c
|
||||
--- xserver/os/WaitFor.c.vnc 2013-04-10 14:51:13.000000000 +0200
|
||||
+++ xserver/os/WaitFor.c 2013-04-10 14:55:40.000000000 +0200
|
||||
@@ -124,6 +124,9 @@ static void DoTimer(OsTimerPtr timer, CA
|
||||
static void CheckAllTimers(void);
|
||||
static OsTimerPtr timers = NULL;
|
||||
|
||||
+extern void vncWriteBlockHandler(fd_set *fds);
|
||||
+extern void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
+
|
||||
/*****************
|
||||
* WaitForSomething:
|
||||
* Make the server suspend until there is
|
||||
@@ -149,6 +152,7 @@ WaitForSomething(int *pClientsReady)
|
||||
INT32 timeout = 0;
|
||||
fd_set clientsReadable;
|
||||
fd_set clientsWritable;
|
||||
+ fd_set socketsWritable;
|
||||
int curclient;
|
||||
int selecterr;
|
||||
static int nready;
|
||||
@@ -207,6 +211,9 @@ WaitForSomething(int *pClientsReady)
|
||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
||||
}
|
||||
|
||||
+ FD_ZERO(&socketsWritable);
|
||||
+ vncWriteBlockHandler(&socketsWritable);
|
||||
+
|
||||
BlockHandler((pointer) &wt, (pointer) &LastSelectMask);
|
||||
if (NewOutputPending)
|
||||
FlushAllOutput();
|
||||
@@ -218,10 +225,20 @@ WaitForSomething(int *pClientsReady)
|
||||
i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
|
||||
}
|
||||
else {
|
||||
- i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ORSET(&socketsWritable, &ClientsWriteBlocked, &socketsWritable);
|
||||
+
|
||||
+ if (XFD_ANYSET(&socketsWritable)) {
|
||||
+ i = Select (MaxClients, &LastSelectMask, &socketsWritable, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ANDSET(&clientsWritable, &socketsWritable, &ClientsWriteBlocked);
|
||||
+ } else {
|
||||
+ i = Select (MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ }
|
||||
}
|
||||
selecterr = GetErrno();
|
||||
WakeupHandler(i, (pointer) &LastSelectMask);
|
||||
+ vncWriteWakeupHandler(i, &socketsWritable);
|
||||
if (i <= 0) { /* An error or timeout occurred */
|
||||
if (dispatchException)
|
||||
return 0;
|
||||
137
unix/xserver116.patch
Normal file
137
unix/xserver116.patch
Normal file
@@ -0,0 +1,137 @@
|
||||
diff -up xorg-server-1.16.0/configure.ac.vnc xorg-server-1.16.0/configure.ac
|
||||
--- xorg-server-1.16.0/configure.ac.vnc 2014-07-17 08:00:51.000000000 +0100
|
||||
+++ xorg-server-1.16.0/configure.ac 2014-09-03 10:21:49.506109235 +0100
|
||||
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
@@ -1795,6 +1796,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1830,6 +1835,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -2051,7 +2058,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2589,6 +2595,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xorg-server-1.16.0/hw/Makefile.am.vnc xorg-server-1.16.0/hw/Makefile.am
|
||||
--- xorg-server-1.16.0/hw/Makefile.am.vnc 2014-04-16 21:24:00.000000000 +0100
|
||||
+++ xorg-server-1.16.0/hw/Makefile.am 2014-09-03 10:21:49.507109234 +0100
|
||||
@@ -38,7 +38,8 @@ SUBDIRS = \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
- $(XWAYLAND_SUBDIRS)
|
||||
+ $(XWAYLAND_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
diff -up xorg-server-1.16.0/mi/miinitext.c.vnc xorg-server-1.16.0/mi/miinitext.c
|
||||
--- xorg-server-1.16.0/mi/miinitext.c.vnc 2014-04-16 21:24:00.000000000 +0100
|
||||
+++ xorg-server-1.16.0/mi/miinitext.c 2014-09-03 10:21:49.508109234 +0100
|
||||
@@ -111,6 +111,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -235,6 +239,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static const ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
diff -up xorg-server-1.16.0/os/WaitFor.c.vnc xorg-server-1.16.0/os/WaitFor.c
|
||||
--- xorg-server-1.16.0/os/WaitFor.c.vnc 2014-02-05 03:08:57.000000000 +0000
|
||||
+++ xorg-server-1.16.0/os/WaitFor.c 2014-09-03 10:21:49.508109234 +0100
|
||||
@@ -125,6 +125,9 @@ static void DoTimer(OsTimerPtr timer, CA
|
||||
static void CheckAllTimers(void);
|
||||
static OsTimerPtr timers = NULL;
|
||||
|
||||
+extern void vncWriteBlockHandler(fd_set *fds);
|
||||
+extern void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
+
|
||||
/*****************
|
||||
* WaitForSomething:
|
||||
* Make the server suspend until there is
|
||||
@@ -150,6 +153,7 @@ WaitForSomething(int *pClientsReady)
|
||||
INT32 timeout = 0;
|
||||
fd_set clientsReadable;
|
||||
fd_set clientsWritable;
|
||||
+ fd_set socketsWritable;
|
||||
int curclient;
|
||||
int selecterr;
|
||||
static int nready;
|
||||
@@ -212,6 +216,9 @@ WaitForSomething(int *pClientsReady)
|
||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
||||
}
|
||||
|
||||
+ FD_ZERO(&socketsWritable);
|
||||
+ vncWriteBlockHandler(&socketsWritable);
|
||||
+
|
||||
BlockHandler((void *) &wt, (void *) &LastSelectMask);
|
||||
if (NewOutputPending)
|
||||
FlushAllOutput();
|
||||
@@ -223,10 +223,20 @@ WaitForSomething(int *pClientsReady)
|
||||
i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
|
||||
}
|
||||
else {
|
||||
- i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ORSET(&socketsWritable, &ClientsWriteBlocked, &socketsWritable);
|
||||
+
|
||||
+ if (XFD_ANYSET(&socketsWritable)) {
|
||||
+ i = Select(MaxClients, &LastSelectMask, &socketsWritable, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ANDSET(&clientsWritable, &socketsWritable, &ClientsWriteBlocked);
|
||||
+ } else {
|
||||
+ i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ }
|
||||
}
|
||||
selecterr = GetErrno();
|
||||
WakeupHandler(i, (void *) &LastSelectMask);
|
||||
+ vncWriteWakeupHandler(i, &socketsWritable);
|
||||
if (i <= 0) { /* An error or timeout occurred */
|
||||
if (dispatchException)
|
||||
return 0;
|
||||
137
unix/xserver117.patch
Normal file
137
unix/xserver117.patch
Normal file
@@ -0,0 +1,137 @@
|
||||
diff -up xorg-server-1.17.1/configure.ac.vnc xorg-server-1.17.1/configure.ac
|
||||
--- xorg-server-1.17.1/configure.ac.vnc 2015-02-10 22:43:52.000000000 +0000
|
||||
+++ xorg-server-1.17.1/configure.ac 2015-02-13 16:14:05.074515927 +0000
|
||||
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
@@ -1795,6 +1796,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1830,6 +1835,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -2059,7 +2066,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2599,6 +2605,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xorg-server-1.17.1/hw/Makefile.am.vnc xorg-server-1.17.1/hw/Makefile.am
|
||||
--- xorg-server-1.17.1/hw/Makefile.am.vnc 2014-04-16 21:24:00.000000000 +0100
|
||||
+++ xorg-server-1.17.1/hw/Makefile.am 2015-02-13 16:14:05.131516821 +0000
|
||||
@@ -38,7 +38,8 @@ SUBDIRS = \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
- $(XWAYLAND_SUBDIRS)
|
||||
+ $(XWAYLAND_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
diff -up xorg-server-1.17.1/mi/miinitext.c.vnc xorg-server-1.17.1/mi/miinitext.c
|
||||
--- xorg-server-1.17.1/mi/miinitext.c.vnc 2015-01-17 23:42:52.000000000 +0000
|
||||
+++ xorg-server-1.17.1/mi/miinitext.c 2015-02-13 16:14:05.131516821 +0000
|
||||
@@ -111,6 +111,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -235,6 +239,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static const ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
diff -up xorg-server-1.17.1/os/WaitFor.c.vnc xorg-server-1.17.1/os/WaitFor.c
|
||||
--- xorg-server-1.17.1/os/WaitFor.c.vnc 2015-01-26 18:40:30.000000000 +0000
|
||||
+++ xorg-server-1.17.1/os/WaitFor.c 2015-02-13 16:14:05.132516837 +0000
|
||||
@@ -125,6 +125,9 @@ static void DoTimer(OsTimerPtr timer, CA
|
||||
static void CheckAllTimers(void);
|
||||
static volatile OsTimerPtr timers = NULL;
|
||||
|
||||
+extern void vncWriteBlockHandler(fd_set *fds);
|
||||
+extern void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
+
|
||||
/*****************
|
||||
* WaitForSomething:
|
||||
* Make the server suspend until there is
|
||||
@@ -150,6 +153,7 @@ WaitForSomething(int *pClientsReady)
|
||||
INT32 timeout = 0;
|
||||
fd_set clientsReadable;
|
||||
fd_set clientsWritable;
|
||||
+ fd_set socketsWritable;
|
||||
int curclient;
|
||||
int selecterr;
|
||||
static int nready;
|
||||
@@ -212,6 +216,9 @@ WaitForSomething(int *pClientsReady)
|
||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
||||
}
|
||||
|
||||
+ FD_ZERO(&socketsWritable);
|
||||
+ vncWriteBlockHandler(&socketsWritable);
|
||||
+
|
||||
BlockHandler((void *) &wt, (void *) &LastSelectMask);
|
||||
if (NewOutputPending)
|
||||
FlushAllOutput();
|
||||
@@ -223,10 +230,20 @@ WaitForSomething(int *pClientsReady)
|
||||
i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
|
||||
}
|
||||
else {
|
||||
- i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ORSET(&socketsWritable, &ClientsWriteBlocked, &socketsWritable);
|
||||
+
|
||||
+ if (XFD_ANYSET(&socketsWritable)) {
|
||||
+ i = Select(MaxClients, &LastSelectMask, &socketsWritable, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ANDSET(&clientsWritable, &socketsWritable, &ClientsWriteBlocked);
|
||||
+ } else {
|
||||
+ i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ }
|
||||
}
|
||||
selecterr = GetErrno();
|
||||
WakeupHandler(i, (void *) &LastSelectMask);
|
||||
+ vncWriteWakeupHandler(i, &socketsWritable);
|
||||
if (i <= 0) { /* An error or timeout occurred */
|
||||
if (dispatchException)
|
||||
return 0;
|
||||
136
unix/xserver118.patch
Normal file
136
unix/xserver118.patch
Normal file
@@ -0,0 +1,136 @@
|
||||
diff -ur xorg-server.orig/configure.ac xorg-server/configure.ac
|
||||
--- xorg-server.orig/configure.ac 2016-04-09 21:28:27.007999965 +0200
|
||||
+++ xorg-server/configure.ac 2016-04-09 21:28:57.587999860 +0200
|
||||
@@ -74,6 +74,7 @@
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
@@ -1828,6 +1829,10 @@
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1863,6 +1868,8 @@
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -2081,7 +2088,6 @@
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2653,6 +2659,7 @@
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -ur xorg-server.orig/hw/Makefile.am xorg-server/hw/Makefile.am
|
||||
--- xorg-server.orig/hw/Makefile.am 2016-04-09 21:28:27.059999965 +0200
|
||||
+++ xorg-server/hw/Makefile.am 2016-04-09 21:28:57.587999860 +0200
|
||||
@@ -43,6 +43,7 @@
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
- $(XWAYLAND_SUBDIRS)
|
||||
+ $(XWAYLAND_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
diff -ur xorg-server.orig/mi/miinitext.c xorg-server/mi/miinitext.c
|
||||
--- xorg-server.orig/mi/miinitext.c 2016-04-09 21:28:27.015999965 +0200
|
||||
+++ xorg-server/mi/miinitext.c 2016-04-09 21:28:57.587999860 +0200
|
||||
@@ -114,6 +114,10 @@
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -238,6 +242,9 @@
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static const ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
diff -ur xorg-server.orig/os/WaitFor.c xorg-server/os/WaitFor.c
|
||||
--- xorg-server.orig/os/WaitFor.c 2016-04-09 21:28:27.071999965 +0200
|
||||
+++ xorg-server/os/WaitFor.c 2016-04-09 21:28:57.587999860 +0200
|
||||
@@ -125,6 +125,9 @@
|
||||
static void CheckAllTimers(void);
|
||||
static volatile OsTimerPtr timers = NULL;
|
||||
|
||||
+extern void vncWriteBlockHandler(fd_set *fds);
|
||||
+extern void vncWriteWakeupHandler(int nfds, fd_set *fds);
|
||||
+
|
||||
/*****************
|
||||
* WaitForSomething:
|
||||
* Make the server suspend until there is
|
||||
@@ -150,6 +153,7 @@
|
||||
INT32 timeout = 0;
|
||||
fd_set clientsReadable;
|
||||
fd_set clientsWritable;
|
||||
+ fd_set socketsWritable;
|
||||
int curclient;
|
||||
int selecterr;
|
||||
static int nready;
|
||||
@@ -213,6 +217,9 @@
|
||||
XFD_COPYSET(&AllSockets, &LastSelectMask);
|
||||
}
|
||||
|
||||
+ FD_ZERO(&socketsWritable);
|
||||
+ vncWriteBlockHandler(&socketsWritable);
|
||||
+
|
||||
BlockHandler((void *) &wt, (void *) &LastSelectMask);
|
||||
if (NewOutputPending)
|
||||
FlushAllOutput();
|
||||
@@ -224,10 +231,20 @@
|
||||
i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
|
||||
}
|
||||
else {
|
||||
- i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ORSET(&socketsWritable, &ClientsWriteBlocked, &socketsWritable);
|
||||
+
|
||||
+ if (XFD_ANYSET(&socketsWritable)) {
|
||||
+ i = Select(MaxClients, &LastSelectMask, &socketsWritable, NULL, wt);
|
||||
+ if (AnyClientsWriteBlocked)
|
||||
+ XFD_ANDSET(&clientsWritable, &socketsWritable, &ClientsWriteBlocked);
|
||||
+ } else {
|
||||
+ i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
|
||||
+ }
|
||||
}
|
||||
selecterr = GetErrno();
|
||||
WakeupHandler(i, (void *) &LastSelectMask);
|
||||
+ vncWriteWakeupHandler(i, &socketsWritable);
|
||||
if (i <= 0) { /* An error or timeout occurred */
|
||||
if (dispatchException)
|
||||
return 0;
|
||||
95
unix/xserver119.patch
Normal file
95
unix/xserver119.patch
Normal file
@@ -0,0 +1,95 @@
|
||||
diff -up xserver/configure.ac.xserver116-rebased xserver/configure.ac
|
||||
--- xserver/configure.ac.xserver116-rebased 2016-09-29 13:14:45.595441590 +0200
|
||||
+++ xserver/configure.ac 2016-09-29 13:14:45.631442006 +0200
|
||||
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
@@ -1863,6 +1864,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1898,6 +1903,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -2116,7 +2123,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2691,6 +2697,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
diff -up xserver/hw/Makefile.am.xserver116-rebased xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.xserver116-rebased 2016-09-29 13:14:45.601441659 +0200
|
||||
+++ xserver/hw/Makefile.am 2016-09-29 13:14:45.631442006 +0200
|
||||
@@ -38,7 +38,8 @@ SUBDIRS = \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
- $(XWAYLAND_SUBDIRS)
|
||||
+ $(XWAYLAND_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
diff -up xserver/mi/miinitext.c.xserver116-rebased xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.xserver116-rebased 2016-09-29 13:14:45.618441855 +0200
|
||||
+++ xserver/mi/miinitext.c 2016-09-29 13:14:45.631442006 +0200
|
||||
@@ -114,6 +114,10 @@ SOFTWARE.
|
||||
#include "micmap.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
*/
|
||||
@@ -238,6 +242,9 @@ EnableDisableExtensionError(const char *
|
||||
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static const ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
--- xserver/include/os.h~ 2016-10-03 09:07:29.000000000 +0200
|
||||
+++ xserver/include/os.h 2016-10-03 14:13:00.013654506 +0200
|
||||
@@ -621,7 +621,7 @@
|
||||
extern _X_EXPORT void
|
||||
LogClose(enum ExitCode error);
|
||||
extern _X_EXPORT Bool
|
||||
-LogSetParameter(LogParameter param, int value);
|
||||
+LogSetParameter(enum _LogParameter param, int value);
|
||||
extern _X_EXPORT void
|
||||
LogVWrite(int verb, const char *f, va_list args)
|
||||
_X_ATTRIBUTE_PRINTF(2, 0);
|
||||
82
unix/xserver120.patch
Normal file
82
unix/xserver120.patch
Normal file
@@ -0,0 +1,82 @@
|
||||
Index: xserver/configure.ac
|
||||
===================================================================
|
||||
--- xserver.orig/configure.ac
|
||||
+++ xserver/configure.ac
|
||||
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AM_PROG_AS
|
||||
+AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
LT_PREREQ([2.2])
|
||||
LT_INIT([disable-static win32-dll])
|
||||
@@ -1777,6 +1778,10 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1812,6 +1817,8 @@ if test "x$XORG" = xauto; then
|
||||
fi
|
||||
AC_MSG_RESULT([$XORG])
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -2029,7 +2036,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2565,6 +2571,7 @@ hw/dmx/Makefile
|
||||
hw/dmx/man/Makefile
|
||||
hw/vfb/Makefile
|
||||
hw/vfb/man/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xnest/man/Makefile
|
||||
hw/xwin/Makefile
|
||||
Index: xserver/hw/Makefile.am
|
||||
===================================================================
|
||||
--- xserver.orig/hw/Makefile.am
|
||||
+++ xserver/hw/Makefile.am
|
||||
@@ -38,7 +38,8 @@ SUBDIRS = \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
- $(XWAYLAND_SUBDIRS)
|
||||
+ $(XWAYLAND_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
Index: xserver/mi/miinitext.c
|
||||
===================================================================
|
||||
--- xserver.orig/mi/miinitext.c
|
||||
+++ xserver/mi/miinitext.c
|
||||
@@ -107,8 +107,15 @@ SOFTWARE.
|
||||
#include "os.h"
|
||||
#include "globals.h"
|
||||
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(void);
|
||||
+#endif
|
||||
+
|
||||
/* List of built-in (statically linked) extensions */
|
||||
static const ExtensionModule staticExtensions[] = {
|
||||
+#ifdef KASMVNC
|
||||
+ {vncExtensionInit, "VNC-EXTENSION", NULL},
|
||||
+#endif
|
||||
{GEExtensionInit, "Generic Event Extension", &noGEExtension},
|
||||
{ShapeExtensionInit, "SHAPE", NULL},
|
||||
#ifdef MITSHM
|
||||
90
unix/xserver17.patch
Normal file
90
unix/xserver17.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2011-05-11 11:09:24.923425002 +0200
|
||||
+++ xserver/configure.ac 2011-05-11 11:09:32.512150522 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.7.7, [https://b
|
||||
RELEASE_DATE="2010-05-04"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([dist-bzip2 foreign])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
shave
|
||||
@@ -64,6 +63,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AC_PROG_CC
|
||||
+AC_PROG_CXX
|
||||
AM_PROG_AS
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
@@ -1383,6 +1383,9 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1421,6 +1424,8 @@ xorg_bus_linuxpci=no
|
||||
xorg_bus_bsdpci=no
|
||||
xorg_bus_sparc=no
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1663,7 +1668,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2108,6 +2112,7 @@ hw/dmx/input/Makefile
|
||||
hw/dmx/glxProxy/Makefile
|
||||
hw/dmx/Makefile
|
||||
hw/vfb/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xwin/Makefile
|
||||
hw/xquartz/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2011-05-11 11:09:24.989422617 +0200
|
||||
+++ xserver/hw/Makefile.am 2011-05-11 11:09:32.512150522 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2011-05-11 11:09:25.089418999 +0200
|
||||
+++ xserver/mi/miinitext.c 2011-05-11 11:09:50.102514343 +0200
|
||||
@@ -274,6 +274,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -454,6 +457,9 @@ InitExtensions(int argc, char *argv[])
|
||||
#ifdef XF86BIGFONT
|
||||
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension) XFree86VidModeExtensionInit();
|
||||
90
unix/xserver18.patch
Normal file
90
unix/xserver18.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2011-05-11 11:11:33.803760465 +0200
|
||||
+++ xserver/configure.ac 2011-05-11 11:11:40.998500216 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.8.2, [https://b
|
||||
RELEASE_DATE="2010-07-01"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros: XORG_DEFAULT_OPTIONS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -64,6 +63,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AC_PROG_CC
|
||||
+AC_PROG_CXX
|
||||
AM_PROG_AS
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
@@ -1505,6 +1505,9 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1543,6 +1546,8 @@ xorg_bus_linuxpci=no
|
||||
xorg_bus_bsdpci=no
|
||||
xorg_bus_sparc=no
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1787,7 +1792,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2231,6 +2235,7 @@ hw/dmx/input/Makefile
|
||||
hw/dmx/glxProxy/Makefile
|
||||
hw/dmx/Makefile
|
||||
hw/vfb/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xwin/Makefile
|
||||
hw/xquartz/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2011-05-11 11:11:33.867758149 +0200
|
||||
+++ xserver/hw/Makefile.am 2011-05-11 11:11:40.998500216 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2011-05-11 11:11:33.941755471 +0200
|
||||
+++ xserver/mi/miinitext.c 2011-05-11 11:12:04.454651752 +0200
|
||||
@@ -274,6 +274,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -454,6 +457,9 @@ InitExtensions(int argc, char *argv[])
|
||||
#ifdef XF86BIGFONT
|
||||
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension) XFree86VidModeExtensionInit();
|
||||
90
unix/xserver19.patch
Normal file
90
unix/xserver19.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
diff -up xserver/configure.ac.vnc xserver/configure.ac
|
||||
--- xserver/configure.ac.vnc 2011-05-11 11:16:50.764292985 +0200
|
||||
+++ xserver/configure.ac 2011-05-11 11:16:55.675101840 +0200
|
||||
@@ -30,7 +30,6 @@ AC_INIT([xorg-server], 1.9.5, [https://b
|
||||
RELEASE_DATE="2011-03-17"
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
AM_INIT_AUTOMAKE([foreign dist-bzip2])
|
||||
-AM_MAINTAINER_MODE
|
||||
|
||||
# Require xorg-macros minimum of 1.10 for XORG_CHECK_SGML_DOCTOOLS
|
||||
m4_ifndef([XORG_MACROS_VERSION],
|
||||
@@ -65,6 +64,7 @@ dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
||||
AC_PROG_CC
|
||||
+AC_PROG_CXX
|
||||
AM_PROG_AS
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
@@ -1514,6 +1514,9 @@ if test "x$XVFB" = xyes; then
|
||||
AC_SUBST([XVFB_SYS_LIBS])
|
||||
fi
|
||||
|
||||
+dnl Xvnc DDX
|
||||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XEXT_INC $FB_INC $MI_INC $RENDER_INC $RANDR_INC"])
|
||||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"])
|
||||
|
||||
dnl Xnest DDX
|
||||
|
||||
@@ -1552,6 +1555,8 @@ xorg_bus_linuxpci=no
|
||||
xorg_bus_bsdpci=no
|
||||
xorg_bus_sparc=no
|
||||
|
||||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
+
|
||||
if test "x$XORG" = xyes; then
|
||||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common'
|
||||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
|
||||
@@ -1798,7 +1803,6 @@ if test "x$XORG" = xyes; then
|
||||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server])
|
||||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server])
|
||||
AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server])
|
||||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version])
|
||||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs])
|
||||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions])
|
||||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server])
|
||||
@@ -2252,6 +2256,7 @@ hw/dmx/input/Makefile
|
||||
hw/dmx/glxProxy/Makefile
|
||||
hw/dmx/Makefile
|
||||
hw/vfb/Makefile
|
||||
+hw/vnc/Makefile
|
||||
hw/xnest/Makefile
|
||||
hw/xwin/Makefile
|
||||
hw/xwin/glx/Makefile
|
||||
diff -up xserver/hw/Makefile.am.vnc xserver/hw/Makefile.am
|
||||
--- xserver/hw/Makefile.am.vnc 2011-05-11 11:16:50.836290382 +0200
|
||||
+++ xserver/hw/Makefile.am 2011-05-11 11:16:55.675101840 +0200
|
||||
@@ -33,7 +33,8 @@ SUBDIRS = \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
- $(XQUARTZ_SUBDIRS)
|
||||
+ $(XQUARTZ_SUBDIRS) \
|
||||
+ vnc
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
diff -up xserver/mi/miinitext.c.vnc xserver/mi/miinitext.c
|
||||
--- xserver/mi/miinitext.c.vnc 2011-05-11 11:16:50.916287489 +0200
|
||||
+++ xserver/mi/miinitext.c 2011-05-11 11:17:12.758477353 +0200
|
||||
@@ -263,6 +263,9 @@ extern void DamageExtensionInit(INITARGS
|
||||
extern void CompositeExtensionInit(INITARGS);
|
||||
#endif
|
||||
extern void GEExtensionInit(INITARGS);
|
||||
+#ifdef KASMVNC
|
||||
+extern void vncExtensionInit(INITARGS);
|
||||
+#endif
|
||||
|
||||
/* The following is only a small first step towards run-time
|
||||
* configurable extensions.
|
||||
@@ -435,6 +438,9 @@ InitExtensions(int argc, char *argv[])
|
||||
#ifdef XF86BIGFONT
|
||||
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
|
||||
#endif
|
||||
+#ifdef KASMVNC
|
||||
+ vncExtensionInit();
|
||||
+#endif
|
||||
#if !defined(NO_HW_ONLY_EXTS)
|
||||
#if defined(XF86VIDMODE)
|
||||
if (!noXFree86VidModeExtension) XFree86VidModeExtensionInit();
|
||||
Reference in New Issue
Block a user