diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27a84a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/tigervnc-1.2.80-20130314svn5065.tar.bz2 diff --git a/.tigervnc.metadata b/.tigervnc.metadata new file mode 100644 index 0000000..afeeeab --- /dev/null +++ b/.tigervnc.metadata @@ -0,0 +1 @@ +581d9ec01dee4602c554ef1d2ae8434d9ea53774 SOURCES/tigervnc-1.2.80-20130314svn5065.tar.bz2 diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/10-libvnc.conf b/SOURCES/10-libvnc.conf new file mode 100644 index 0000000..a053a7d --- /dev/null +++ b/SOURCES/10-libvnc.conf @@ -0,0 +1,19 @@ +# This file contains configuration of libvnc.so module +# +# To get libvnc.so module working, do this: +# 1. run "vncpasswd" from tigervnc-server package as root user +# 2. uncomment configuration lines below +# +# Please note you can specify any option which Xvnc accepts. +# Refer to `Xvnc -help` output for detailed list of options. + +#Section "Module" +# Load "vnc" +#EndSection + +#Section "Screen" +# Identifier "Screen0 +# DefaultDepth 16 +# Option "SecurityTypes" "VncAuth" +# Option "PasswordFile" "/root/.vnc/passwd" +#EndSection diff --git a/SOURCES/tigervnc-1.3.0-xserver-1.15.patch b/SOURCES/tigervnc-1.3.0-xserver-1.15.patch new file mode 100644 index 0000000..d070a70 --- /dev/null +++ b/SOURCES/tigervnc-1.3.0-xserver-1.15.patch @@ -0,0 +1,15 @@ +diff -up tigervnc-1.3.0/unix/xserver/hw/vnc/xorg-version.h.jx tigervnc-1.3.0/unix/xserver/hw/vnc/xorg-version.h +--- tigervnc-1.3.0/unix/xserver/hw/vnc/xorg-version.h.jx 2013-07-01 08:41:24.000000000 -0400 ++++ tigervnc-1.3.0/unix/xserver/hw/vnc/xorg-version.h 2013-11-07 11:39:49.749992669 -0500 +@@ -44,8 +44,10 @@ + #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 + #else +-#error "X.Org newer than 1.14 is not supported" ++#error "X.Org newer than 1.15 is not supported" + #endif + + #endif diff --git a/SOURCES/tigervnc-CVE-2014-0011.patch b/SOURCES/tigervnc-CVE-2014-0011.patch new file mode 100644 index 0000000..0075720 --- /dev/null +++ b/SOURCES/tigervnc-CVE-2014-0011.patch @@ -0,0 +1,49 @@ +diff -up tigervnc-1.3.0/common/CMakeLists.txt.CVE-2014-0011 tigervnc-1.3.0/common/CMakeLists.txt +--- tigervnc-1.3.0/common/CMakeLists.txt.CVE-2014-0011 2013-07-01 13:42:01.000000000 +0100 ++++ tigervnc-1.3.0/common/CMakeLists.txt 2014-02-04 16:59:10.840037314 +0000 +@@ -23,3 +23,6 @@ if(CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_S + set_target_properties(zlib PROPERTIES COMPILE_FLAGS -fPIC) + endif() + endif() ++ ++# Turn asserts on. ++set_target_properties(rdr rfb PROPERTIES COMPILE_FLAGS -UNDEBUG) +diff -up tigervnc-1.3.0/common/rfb/zrleDecode.h.CVE-2014-0011 tigervnc-1.3.0/common/rfb/zrleDecode.h +--- tigervnc-1.3.0/common/rfb/zrleDecode.h.CVE-2014-0011 2013-07-01 13:41:59.000000000 +0100 ++++ tigervnc-1.3.0/common/rfb/zrleDecode.h 2014-02-04 16:17:00.881565540 +0000 +@@ -25,9 +25,10 @@ + // FILL_RECT - fill a rectangle with a single colour + // IMAGE_RECT - draw a rectangle of pixel data from a buffer + ++#include + #include + #include +-#include ++#include + + namespace rfb { + +@@ -143,7 +144,10 @@ void ZRLE_DECODE (const Rect& r, rdr::In + len += b; + } while (b == 255); + +- assert(len <= end - ptr); ++ if (end - ptr < len) { ++ fprintf (stderr, "ZRLE decode error\n"); ++ throw Exception ("ZRLE decode error"); ++ } + + #ifdef FAVOUR_FILL_RECT + int i = ptr - buf; +@@ -193,7 +197,10 @@ void ZRLE_DECODE (const Rect& r, rdr::In + len += b; + } while (b == 255); + +- assert(len <= end - ptr); ++ if (end - ptr < len) { ++ fprintf (stderr, "ZRLE decode error\n"); ++ throw Exception ("ZRLE decode error"); ++ } + } + + index &= 127; diff --git a/SOURCES/tigervnc-cookie.patch b/SOURCES/tigervnc-cookie.patch new file mode 100644 index 0000000..c066a5f --- /dev/null +++ b/SOURCES/tigervnc-cookie.patch @@ -0,0 +1,37 @@ +diff -up tigervnc-1.0.90-20091221svn3929/unix/vncserver.cookie tigervnc-1.0.90-20091221svn3929/unix/vncserver +--- tigervnc-1.0.90-20091221svn3929/unix/vncserver.cookie 2009-11-12 11:39:54.000000000 +0100 ++++ tigervnc-1.0.90-20091221svn3929/unix/vncserver 2009-12-21 16:15:01.907799091 +0100 +@@ -189,27 +189,12 @@ $vncPort = 5900 + $displayNumber; + $desktopLog = "$vncUserDir/$host:$displayNumber.log"; + unlink($desktopLog); + +-# Make an X server cookie - 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. +- +-my $cookie = ""; +-if (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); +- } +-} +- +-system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie"); +-system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie"); ++# Make an X server cookie - use mcookie ++$cookie = `/usr/bin/mcookie`; ++open (XAUTH, "|xauth -f $xauthorityFile source -"); ++print XAUTH "add $host:$displayNumber . $cookie\n"; ++print XAUTH "add $host/unix:$displayNumber . $cookie\n"; ++close XAUTH; + + if ($opt{'-name'}) { + $desktopName = $opt{'-name'}; diff --git a/SOURCES/tigervnc-cursor.patch b/SOURCES/tigervnc-cursor.patch new file mode 100644 index 0000000..349c950 --- /dev/null +++ b/SOURCES/tigervnc-cursor.patch @@ -0,0 +1,12 @@ +diff -up tigervnc-1.3.0/vncviewer/Viewport.cxx.cursor tigervnc-1.3.0/vncviewer/Viewport.cxx +--- tigervnc-1.3.0/vncviewer/Viewport.cxx.cursor 2013-12-17 13:28:23.170400013 +0000 ++++ tigervnc-1.3.0/vncviewer/Viewport.cxx 2013-12-17 13:29:46.095784064 +0000 +@@ -931,7 +931,7 @@ void Viewport::popupContextMenu() + + // Back to our proper mouse pointer. + #ifdef HAVE_FLTK_CURSOR +- if (Fl::belowmouse() == this) ++ if (Fl::belowmouse() == this && cursor) + window()->cursor(cursor, cursorHotspot.x, cursorHotspot.y); + #endif + diff --git a/SOURCES/tigervnc-inetd-nowait.patch b/SOURCES/tigervnc-inetd-nowait.patch new file mode 100644 index 0000000..89b3d19 --- /dev/null +++ b/SOURCES/tigervnc-inetd-nowait.patch @@ -0,0 +1,53 @@ +diff -up tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.cxx.inetd-nowait tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.cxx +--- tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.cxx.inetd-nowait 2013-05-23 12:20:35.836386218 +0100 ++++ tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.cxx 2013-05-23 12:23:04.698003213 +0100 +@@ -325,18 +325,12 @@ bool TcpSocket::cork(int sock, bool enab + #endif + } + +-bool TcpSocket::isSocket(int sock) ++bool TcpSocket::isListening(int sock) + { +- struct sockaddr_in info; +- socklen_t info_size = sizeof(info); +- return getsockname(sock, (struct sockaddr *)&info, &info_size) >= 0; +-} +- +-bool TcpSocket::isConnected(int sock) +-{ +- struct sockaddr_in info; +- socklen_t info_size = sizeof(info); +- return getpeername(sock, (struct sockaddr *)&info, &info_size) >= 0; ++ int listening = 0; ++ socklen_t listening_size = sizeof(listening); ++ return getsockopt(sock, SOL_SOCKET, SO_ACCEPTCONN, &listening, ++ &listening_size) >= 0 && listening; + } + + int TcpSocket::getSockPort(int sock) +diff -up tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.h.inetd-nowait tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.h +--- tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.h.inetd-nowait 2013-05-23 12:20:35.835386220 +0100 ++++ tigervnc-1.2.80-20130314svn5065/common/network/TcpSocket.h 2013-05-23 12:21:58.861730647 +0100 +@@ -57,8 +57,7 @@ namespace network { + + static bool enableNagles(int sock, bool enable); + static bool cork(int sock, bool enable); +- static bool isSocket(int sock); +- static bool isConnected(int sock); ++ static bool isListening(int sock); + static int getSockPort(int sock); + private: + bool closeFd; +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/vncExtInit.cc.inetd-nowait tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/vncExtInit.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/vncExtInit.cc.inetd-nowait 2013-03-14 17:11:22.000000000 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/vncExtInit.cc 2013-05-23 12:21:10.545530308 +0100 +@@ -225,8 +225,7 @@ void vncExtensionInit() + network::TcpListener* listener = 0; + network::TcpListener* httpListener = 0; + if (scr == 0 && vncInetdSock != -1) { +- if (network::TcpSocket::isSocket(vncInetdSock) && +- !network::TcpSocket::isConnected(vncInetdSock)) ++ if (network::TcpSocket::isListening(vncInetdSock)) + { + listener = new network::TcpListener(NULL, 0, 0, vncInetdSock, true); + vlog.info("inetd wait"); diff --git a/SOURCES/tigervnc-input.patch b/SOURCES/tigervnc-input.patch new file mode 100644 index 0000000..e1e7b0b --- /dev/null +++ b/SOURCES/tigervnc-input.patch @@ -0,0 +1,2569 @@ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc.input 2012-08-29 09:56:37.000000000 +0100 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc 2014-01-17 16:01:13.140109450 +0000 +@@ -1,5 +1,6 @@ + /* Copyright (C) 2009 TightVNC Team + * Copyright (C) 2009 Red Hat, Inc. ++ * Copyright 2013 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 +@@ -34,16 +35,6 @@ extern "C" { + #include "inpututils.h" + #endif + #include "mi.h" +-#ifndef XKB_IN_SERVER +-#define XKB_IN_SERVER +-#endif +-#ifdef XKB +-/* +- * This include is needed to use XkbConvertCase instead of XConvertCase even if +- * we don't use XKB extension. +- */ +-#include +-#endif + #if XORG >= 16 + #include "exevents.h" + #endif +@@ -58,6 +49,7 @@ CopyKeyClass(DeviceIntPtr device, Device + extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey; + #endif + #include ++#include + #include + #undef public + #undef class +@@ -72,12 +64,9 @@ using namespace rfb; + + static LogWriter vlog("Input"); + +-#define BUTTONS 7 +-static int pointerProc(DeviceIntPtr pDevice, int onoff); ++rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock", "Avoid fake Shift presses for keys affected by NumLock.", true); + +-static int keyboardProc(DeviceIntPtr pDevice, int onoff); +-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col); +-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); ++#define BUTTONS 7 + + /* Event queue is shared between all devices. */ + #if XORG == 15 +@@ -128,26 +117,16 @@ static void enqueueEvents(DeviceIntPtr d + #endif /* XORG < 111 */ + + InputDevice::InputDevice(rfb::VNCServerST *_server) +- : server(_server), oldButtonMask(0) ++ : server(_server), initialized(false), oldButtonMask(0) + { +-#if XORG < 17 +- pointerDev = AddInputDevice( +-#if XORG >= 16 +- serverClient, +-#endif +- pointerProc, TRUE); +- RegisterPointerDevice(pointerDev); ++ int i; + +- keyboardDev = AddInputDevice( +-#if XORG >= 16 +- serverClient, +-#endif +- keyboardProc, TRUE); +- RegisterKeyboardDevice(keyboardDev); +-#endif + #if XORG < 111 + initEventq(); + #endif ++ ++ for (i = 0;i < 256;i++) ++ pressedKeys[i] = NoSymbol; + } + + void InputDevice::PointerButtonAction(int buttonMask) +@@ -160,8 +139,6 @@ void InputDevice::PointerButtonAction(in + ValuatorMask mask; + #endif + +- initInputDevice(); +- + for (i = 0; i < BUTTONS; i++) { + if ((buttonMask ^ oldButtonMask) & (1 << i)) { + int action = (buttonMask & (1< 0) ++ vncBell(); ++} ++ ++extern void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap); ++ ++static int keyboardProc(DeviceIntPtr pDevice, int onoff) ++{ ++#if XORG < 17 ++ KeySymsRec keySyms; ++ CARD8 modMap[MAP_LENGTH]; ++#endif ++ DevicePtr pDev = (DevicePtr)pDevice; ++ ++ switch (onoff) { ++ case DEVICE_INIT: ++#if XORG < 17 ++ GetInitKeyboardMap(&keySyms, modMap); ++#endif ++ InitKeyboardDeviceStruct( + #if XORG >= 17 +- int ret; +- static int initialized = 0; ++ pDevice, NULL, ++#else ++ pDev, &keySyms, modMap, ++#endif ++ keyboardBell, (KbdCtrlProcPtr)NoopDDA); ++ break; ++ case DEVICE_ON: ++ pDev->on = TRUE; ++ break; ++ case DEVICE_OFF: ++ pDev->on = FALSE; ++ break; ++ } + +- if (initialized != 0) ++ return Success; ++} ++ ++void InputDevice::InitInputDevice(void) ++{ ++ if (initialized) + return; + +- initialized = 1; ++ initialized = true; ++ ++#if XORG < 17 ++ pointerDev = AddInputDevice( ++#if XORG >= 16 ++ serverClient, ++#endif ++ pointerProc, TRUE); ++ RegisterPointerDevice(pointerDev); ++ ++ keyboardDev = AddInputDevice( ++#if XORG >= 16 ++ serverClient, ++#endif ++ keyboardProc, TRUE); ++ RegisterKeyboardDevice(keyboardDev); ++ ++ if (ActivateDevice(pointerDev) != Success || ++ ActivateDevice(keyboardDev) != Success) ++ FatalError("Failed to activate TigerVNC devices\n"); ++ ++ if (!EnableDevice(pointerDev) || ++ !EnableDevice(keyboardDev)) ++ FatalError("Failed to enable TigerVNC devices\n"); ++#else /* < 17 */ ++ int ret; + + ret = AllocDevicePair(serverClient, "TigerVNC", &pointerDev, + &keyboardDev, pointerProc, keyboardProc, +@@ -312,7 +349,9 @@ void InputDevice::initInputDevice(void) + if (!EnableDevice(pointerDev, TRUE) || + !EnableDevice(keyboardDev, TRUE)) + FatalError("Failed to activate TigerVNC devices\n"); +-#endif ++#endif /* 17 */ ++ ++ PrepareInputDevices(); + } + + static inline void pressKey(DeviceIntPtr dev, int kc, bool down, const char *msg) +@@ -334,143 +373,6 @@ static inline void pressKey(DeviceIntPtr + #endif + } + +-#define IS_PRESSED(keyc, keycode) \ +- ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) +- +-/* +- * ModifierState is a class which helps simplify generating a "fake" press or +- * release of shift, ctrl, alt, etc. An instance of the class is created for +- * every modifier which may need to be pressed or released. Then either +- * press() or release() may be called to make sure that the corresponding keys +- * are in the right state. The destructor of the class automatically reverts +- * to the previous state. Each modifier may have multiple keys associated with +- * it, so in the case of a fake release, this may involve releasing more than +- * one key. +- */ +- +-class ModifierState { +-public: +- ModifierState(DeviceIntPtr _dev, int _modIndex) +- : modIndex(_modIndex), nKeys(0), keys(0), pressed(false), +- dev(_dev) {} +- +- ~ModifierState() +- { +- for (int i = 0; i < nKeys; i++) +- pressKey(dev, keys[i], !pressed, "fake keycode"); +- delete [] keys; +- } +- +- void press() +- { +- int state, maxKeysPerMod, keycode; +-#if XORG >= 17 +- KeyCode *modmap = NULL; +-#if XORG >= 111 +- state = XkbStateFieldFromRec(&dev->master->key->xkbInfo->state); +-#else /* XORG >= 111 */ +- state = XkbStateFieldFromRec(&dev->u.master->key->xkbInfo->state); +-#endif /* XORG >= 111 */ +-#else +- KeyClassPtr keyc = dev->key; +- state = keyc->state; +-#endif +- if ((state & (1 << modIndex)) != 0) +- return; +- +-#if XORG >= 17 +- if (generate_modkeymap(serverClient, dev, &modmap, +- &maxKeysPerMod) != Success) { +- vlog.error("generate_modkeymap failed"); +- return; +- } +- +- if (maxKeysPerMod == 0) { +- vlog.debug("Keyboard has no modifiers"); +- xfree(modmap); +- return; +- } +- +- keycode = modmap[modIndex * maxKeysPerMod]; +- xfree(modmap); +-#else +- maxKeysPerMod = keyc->maxKeysPerModifier; +- keycode = keyc->modifierKeyMap[modIndex * maxKeysPerMod]; +-#endif +- tempKeyEvent(keycode, true, maxKeysPerMod); +- pressed = true; +- } +- +- void release() +- { +- int state, maxKeysPerMod; +- KeyClassPtr keyc; +-#if XORG >= 17 +- KeyCode *modmap = NULL; +- +-#if XORG >= 111 +- keyc = dev->master->key; +-#else /* XORG >= 111 */ +- keyc = dev->u.master->key; +-#endif /* XORG >= 111 */ +- state = XkbStateFieldFromRec(&keyc->xkbInfo->state); +-#else +- keyc = dev->key; +- state = keyc->state; +-#endif +- if ((state & (1 << modIndex)) == 0) +- return; +- +-#if XORG >= 17 +- if (generate_modkeymap(serverClient, dev, &modmap, +- &maxKeysPerMod) != Success) { +- vlog.error("generate_modkeymap failed"); +- return; +- } +- +- if (maxKeysPerMod == 0) { +- vlog.debug("Keyboard has no modifiers"); +- xfree(modmap); +- return; +- } +-#else +- maxKeysPerMod = keyc->maxKeysPerModifier; +-#endif +- +- for (int k = 0; k < maxKeysPerMod; k++) { +- int keycode; +- int index = modIndex * maxKeysPerMod + k; +-#if XORG >= 17 +- keycode = modmap[index]; +-#else +- keycode = keyc->modifierKeyMap[index]; +-#endif +- if (keycode && IS_PRESSED(keyc, keycode)) +- tempKeyEvent(keycode, false, maxKeysPerMod); +- } +-#if XORG >= 17 +- xfree(modmap); +-#endif +- } +- +-private: +- void tempKeyEvent(int keycode, bool down, int maxKeysPerMod) +- { +- if (keycode) { +- if (!keys) keys = new int[maxKeysPerMod]; +- keys[nKeys++] = keycode; +- pressKey(dev, keycode, down, "fake keycode"); +- } +- } +- +- int modIndex; +- int nKeys; +- int *keys; +- bool pressed; +- DeviceIntPtr dev; +-}; +- +- + /* altKeysym is a table of alternative keysyms which have the same meaning. */ + + static struct altKeysym_t { +@@ -517,102 +419,48 @@ static struct altKeysym_t { + { XK_KP_7, XK_7 }, + { XK_KP_8, XK_8 }, + { XK_KP_9, XK_9 }, ++ { XK_ISO_Level3_Shift, XK_Mode_switch }, + }; + + /* + * keyEvent() - work out the best keycode corresponding to the keysym sent by +- * the viewer. This is non-trivial because we can't assume much about the +- * local keyboard layout. We must also find out which column of the keyboard +- * mapping the keysym is in, and alter the shift state appropriately. Column 0 +- * means both shift and "mode_switch" (AltGr) must be released, column 1 means +- * shift must be pressed and mode_switch released, column 2 means shift must be +- * released and mode_switch pressed, and column 3 means both shift and +- * mode_switch must be pressed. +- * +- * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org +- * version. Quick explanation of that "magic": +- * +- * 1.5 +- * - has only one core keyboard so we have to keep core keyboard mapping +- * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard() +- * +- * 1.6 (aka MPX - Multi pointer X) +- * - multiple master devices (= core devices) exists, keep vncKeyboardDevice +- * synchronized with proper master device +- */ +- +-#if XORG >= 17 +-#define FREE_MAPS \ +- do { \ +- xfree(modmap); \ +- xfree(keymap->map); \ +- xfree(keymap); \ +- } while (0); +-#else +-#define FREE_MAPS +-#endif +- +-#if XORG >= 17 +-/* +- * Modifier keysyms must be handled differently. Instead of finding +- * the right row and collumn in the keymap, directly press/release +- * the keycode which is mapped as modifier with the same keysym. +- * +- * This will avoid issues when there are multiple modifier keysyms +- * in the keymap but only some of them are mapped as modifiers in +- * the modmap. +- * +- * Returns keycode of the modifier key. ++ * 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 inline int isModifier(KeySymsPtr keymap, KeyCode *modmap, +- int maxKeysPerMod, rdr::U32 keysym) ++void InputDevice::keyEvent(rdr::U32 keysym, bool down) + { +- KeySym *map = keymap->map; +- KeyCode minKeyCode = keymap->minKeyCode; +- int mapWidth = keymap->mapWidth; +- int i, j, k; +- +- /* Find modifier index in the modmap */ +- for (i = 0; i < 8; i++) { +- for (k = 0; k < maxKeysPerMod; k++) { +- int index = i * maxKeysPerMod + k; +- int keycode = modmap[index]; ++ int i; ++ unsigned state, new_state; ++ KeyCode keycode; + +- if (keycode == 0) +- continue; ++ unsigned level_three_mask; ++ KeyCode shift_press, level_three_press; ++ std::list shift_release, level_three_release; + +- for (j = 0; j < mapWidth; j++) { +- if (map[(keycode - minKeyCode) * mapWidth + j] +- == keysym) { +- return keycode; +- } ++ /* ++ * 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(keyboardDev, i, false, "keycode"); ++ mieqProcessInputEvents(); ++ return; + } + } +- } +- +- return -1; /* Not a modifier */ +-} +-#endif + +-void InputDevice::keyEvent(rdr::U32 keysym, bool down) +-{ +-#if XORG < 17 +- DeviceIntPtr master; +-#endif +- KeyClassPtr keyc; +- KeySymsPtr keymap = NULL; +- KeySym *map = NULL; +- KeyCode minKeyCode, maxKeyCode; +- KeyCode *modmap = NULL; +- int mapWidth; +- unsigned int i; +- int j, k, state, maxKeysPerMod; +-#if XORG >= 17 +- KeybdCtrl ctrl; +-#endif +- +- initInputDevice(); ++ /* ++ * This can happen quite often as we ignore some ++ * key presses. ++ */ ++ vlog.debug("Unexpected release of keysym 0x%x", keysym); ++ return; ++ } + + /* + * Since we are checking the current state to determine if we need +@@ -622,543 +470,214 @@ void InputDevice::keyEvent(rdr::U32 keys + */ + mieqProcessInputEvents(); + +- if (keysym == XK_Caps_Lock) { +- vlog.debug("Ignoring caps lock"); +- return; +- } ++ state = getKeyboardState(); + +-#if XORG >= 17 +-#if XORG >= 111 +- keyc = keyboardDev->master->key; +-#else /* XORG >= 111 */ +- keyc = keyboardDev->u.master->key; +-#endif /* XORG >= 111 */ +- +- keymap = XkbGetCoreMap(keyboardDev); +- if (!keymap) { +- vlog.error("VNC keyboard device has no map"); +- return; +- } ++ keycode = keysymToKeycode(keysym, state, &new_state); + +- if (generate_modkeymap(serverClient, keyboardDev, &modmap, +- &maxKeysPerMod) != Success) { +- vlog.error("generate_modkeymap failed"); +- xfree(keymap->map); +- xfree(keymap); +- return; +- } +- +- if (maxKeysPerMod == 0) +- vlog.debug("Keyboard has no modifiers"); +- +- state = XkbStateFieldFromRec(&keyc->xkbInfo->state); +-#else +- keyc = keyboardDev->key; +- state = keyc->state; +- maxKeysPerMod = keyc->maxKeysPerModifier; +- keymap = &keyc->curKeySyms; +- modmap = keyc->modifierKeyMap; +-#endif +- map = keymap->map; +- minKeyCode = keymap->minKeyCode; +- maxKeyCode = keymap->maxKeyCode; +- mapWidth = keymap->mapWidth; +- +-#if XORG >= 17 +- /* +- * No server-side key repeating, please. Some clients won't work well, +- * check https://bugzilla.redhat.com/show_bug.cgi?id=607866. +- */ +- ctrl = keyboardDev->kbdfeed->ctrl; +- if (ctrl.autoRepeat != FALSE) { +- ctrl.autoRepeat = FALSE; +- XkbSetRepeatKeys(keyboardDev, -1, ctrl.autoRepeat); +- } +-#endif +- +- /* find which modifier Mode_switch is on. */ +- int modeSwitchMapIndex = 0; +- for (i = 3; i < 8; i++) { +- for (k = 0; k < maxKeysPerMod; k++) { +- int index = i * maxKeysPerMod + k; +- int keycode = modmap[index]; +- +- if (keycode == 0) ++ /* 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; + +- for (j = 0; j < mapWidth; j++) { +- if (map[(keycode - minKeyCode) * mapWidth + j] +- == XK_Mode_switch) { +- modeSwitchMapIndex = i; +- goto ModeSwitchFound; +- } +- } ++ keycode = keysymToKeycode(altsym, state, &new_state); ++ if (keycode != 0) ++ break; + } + } +-ModeSwitchFound: + +- int kc; +- int col = 0; ++ /* We don't have lock synchronisation... */ ++ if (isLockModifier(keycode, new_state)) { ++ vlog.debug("Ignoring lock key (e.g. caps lock)"); ++ return; ++ } + +-#if XORG >= 17 +- if ((kc = isModifier(keymap, modmap, maxKeysPerMod, keysym)) != -1) { +- /* +- * It is a modifier key event. +- * +- * Don't do any auto-repeat because the X server will translate +- * each press into a release followed by a press. +- */ +- if (IS_PRESSED(keyc, kc) && down) { +- FREE_MAPS; ++ /* No matches. Will have to add a new entry... */ ++ if (keycode == 0) { ++ keycode = addKeysym(keysym, state); ++ if (keycode == 0) { ++ vlog.error("Failure adding new keysym 0x%x", keysym); + return; + } + +- goto press; +- } +-#endif +- +- if (maxKeysPerMod != 0) { +- if ((state & (1 << ShiftMapIndex)) != 0) +- col |= 1; +- if (modeSwitchMapIndex != 0 && +- ((state & (1 << modeSwitchMapIndex))) != 0) +- col |= 2; +- } +- +- kc = KeysymToKeycode(keymap, keysym, &col); ++ vlog.info("Added unknown keysym 0x%x to keycode %d", ++ keysym, keycode); + +- /* +- * Sort out the "shifted Tab" mess. If we are sent a shifted Tab, +- * generate a local shifted Tab regardless of what the "shifted Tab" +- * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or +- * HP's private BackTab keysym, and quite possibly some others too). +- * We never get ISO_Left_Tab here because it's already been translated +- * in VNCSConnectionST. +- */ +- if (maxKeysPerMod != 0 && keysym == XK_Tab && +- ((state & (1 << ShiftMapIndex))) != 0) +- col |= 1; +- +- if (kc == 0) { + /* +- * Not a direct match in the local keyboard mapping. Check for +- * alternative keysyms with the same meaning. ++ * The state given to addKeysym() is just a hint and ++ * the actual result might still require some state ++ * changes. + */ +- for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { +- if (keysym == altKeysym[i].a) +- kc = KeysymToKeycode(keymap, altKeysym[i].b, +- &col); +- else if (keysym == altKeysym[i].b) +- kc = KeysymToKeycode(keymap, altKeysym[i].a, +- &col); +- if (kc) +- break; ++ keycode = keysymToKeycode(keysym, state, &new_state); ++ if (keycode == 0) { ++ vlog.error("Newly added keysym 0x%x cannot be generated", keysym); ++ return; + } + } + +- if (kc == 0) { +- /* Dynamically add a new key to the keyboard mapping. */ +- for (kc = maxKeyCode; kc >= minKeyCode; kc--) { +- if (map[(kc - minKeyCode) * mapWidth] != 0) ++ /* ++ * 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)) && ++ avoidShiftNumLock && isAffectedByNumLock(keycode)) { ++ KeyCode keycode2; ++ unsigned new_state2; ++ ++ vlog.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; + +- map[(kc - minKeyCode) * mapWidth] = keysym; +- col = 0; ++ keycode2 = keysymToKeycode(altsym, state, &new_state2); ++ if (keycode2 == 0) ++ continue; + +- vlog.info("Added unknown keysym 0x%x to keycode %d", +- keysym, kc); ++ if (((state & ShiftMask) != (new_state2 & ShiftMask)) && ++ isAffectedByNumLock(keycode2)) ++ continue; + +-#if XORG < 17 +-#if XORG == 15 +- master = inputInfo.keyboard; +-#else +- master = keyboardDev->u.master; +-#endif +- void *slave = dixLookupPrivate(&master->devPrivates, +- CoreDevicePrivateKey); +- if (keyboardDev == slave) { +- dixSetPrivate(&master->devPrivates, +- CoreDevicePrivateKey, NULL); +-#if XORG == 15 +- SwitchCoreKeyboard(keyboardDev); +-#else +- CopyKeyClass(keyboardDev, master); +-#endif +- } +-#else /* XORG < 17 */ +- XkbApplyMappingChange(keyboardDev, keymap, minKeyCode, +- maxKeyCode - minKeyCode + 1, +- NULL, serverClient); +-#if XORG >= 111 +- XkbCopyDeviceKeymap(keyboardDev->master, keyboardDev); +-#else +- XkbCopyDeviceKeymap(keyboardDev->u.master, keyboardDev); +-#endif +-#endif /* XORG < 17 */ + break; + } +- } + +- if (kc < minKeyCode) { +- vlog.info("Keyboard mapping full - ignoring unknown keysym " +- "0x%x",keysym); +- FREE_MAPS; +- return; +- } +- +-#if XORG < 17 +- /* +- * See if it's a modifier key. If so, then don't do any auto-repeat, +- * because the X server will translate each press into a release +- * followed by a press. +- */ +- for (i = 0; i < 8; i++) { +- for (k = 0; k < maxKeysPerMod; k++) { +- int index = i * maxKeysPerMod + k; +- if (kc == modmap[index] && IS_PRESSED(keyc,kc) && down) { +- FREE_MAPS; +- return; +- } ++ if (i == sizeof(altKeysym)/sizeof(altKeysym[0])) ++ vlog.debug("No alternative keysym found"); ++ else { ++ keycode = keycode2; ++ new_state = new_state2; + } + } +-#else ++ + /* +- * If you would like to press a key which is already pressed then +- * viewer didn't send the "release" event. In this case release it +- * before the press. ++ * "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 (IS_PRESSED(keyc, kc) && down) { +- vlog.debug("KeyRelease for %d wasn't sent, releasing", kc); +- pressKey(keyboardDev, kc, false, "fixing keycode"); +- } +-#endif ++ if (keysym == XK_Tab && (state & ShiftMask)) ++ new_state |= ShiftMask; + +- if (maxKeysPerMod != 0) { +- ModifierState shift(keyboardDev, ShiftMapIndex); +- ModifierState modeSwitch(keyboardDev, modeSwitchMapIndex); +- if (down) { +- if (col & 1) +- shift.press(); +- else +- shift.release(); +- if (modeSwitchMapIndex) { +- if (col & 2) +- modeSwitch.press(); +- else +- modeSwitch.release(); +- } +- } +- /* +- * Ensure ModifierState objects are not destroyed before +- * pressKey call, otherwise fake modifier keypress can be lost. +- */ +- pressKey(keyboardDev, kc, down, "keycode"); +- } else { +-press: +- pressKey(keyboardDev, kc, down, "keycode"); +- } +- +- +- FREE_MAPS; +- + /* +- * 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. ++ * We need a bigger state change than just shift, ++ * so we need to know what the mask is for level 3 shifts. + */ +- mieqProcessInputEvents(); +-} +- +-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) +-{ +- int per = keymap->mapWidth; +- KeySym *syms; +- KeySym lsym, usym; +- +- if ((col < 0) || ((col >= per) && (col > 3)) || +- (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) +- return NoSymbol; +- +- syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; +- if (col >= 4) +- return syms[col]; +- +- if (col > 1) { +- while ((per > 2) && (syms[per - 1] == NoSymbol)) +- per--; +- if (per < 3) +- col -= 2; +- } +- +- if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { +- XkbConvertCase +- (syms[col&~1], &lsym, &usym); +- if (!(col & 1)) +- return lsym; +- /* +- * I'm commenting out this logic because it's incorrect even +- * though it was copied from the Xlib sources. The X protocol +- * book quite clearly states that where a group consists of +- * element 1 being a non-alphabetic keysym and element 2 being +- * NoSymbol that you treat the second element as being the +- * same as the first. This also tallies with the behaviour +- * produced by the installed Xlib on my linux box (I believe +- * this is because it uses some XKB code rather than the +- * original Xlib code - compare XKBBind.c with KeyBind.c in +- * lib/X11). +- */ +-#if 0 +- else if (usym == lsym) +- return NoSymbol; +-#endif +- else +- return usym; +- } +- +- return syms[col]; +-} ++ if ((new_state & ~ShiftMask) != (state & ~ShiftMask)) ++ level_three_mask = getLevelThreeMask(); ++ else ++ level_three_mask = 0; ++ ++ shift_press = level_three_press = 0; ++ ++ /* Need a fake press or release of shift? */ ++ if (!(state & ShiftMask) && (new_state & ShiftMask)) { ++ shift_press = pressShift(); ++ if (shift_press == 0) { ++ vlog.error("Unable to find a modifier key for Shift"); ++ return; ++ } + +-/* +- * KeysymToKeycode() - find the keycode and column corresponding to the given +- * keysym. The value of col passed in should be the column determined from the +- * current shift state. If the keysym can be found in that column we prefer +- * that to finding it in a different column (which would require fake events to +- * alter the shift state). +- */ +-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) +-{ +- int i, j; ++ pressKey(keyboardDev, shift_press, true, "temp shift"); ++ } else if ((state & ShiftMask) && !(new_state & ShiftMask)) { ++ std::list::const_iterator iter; ++ ++ shift_release = releaseShift(); ++ if (shift_release.empty()) { ++ vlog.error("Unable to find the modifier key(s) for releasing Shift"); ++ return; ++ } + +- j = *col; +- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { +- if (KeyCodetoKeySym(keymap, i, j) == ks) +- return i; ++ for (iter = shift_release.begin();iter != shift_release.end();++iter) ++ pressKey(keyboardDev, *iter, false, "temp shift"); + } + +- for (j = 0; j < keymap->mapWidth; j++) { +- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { +- if (KeyCodetoKeySym(keymap, i, j) == ks) { +- *col = j; +- return i; +- } ++ /* Need a fake press or release of level three shift? */ ++ if (!(state & level_three_mask) && (new_state & level_three_mask)) { ++ level_three_press = pressLevelThree(); ++ if (level_three_press == 0) { ++ vlog.error("Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch"); ++ return; + } +- } + +- return 0; +-} +- +-#if XORG < 17 +-/* Fairly standard US PC Keyboard */ +- +-#define MIN_KEY 8 +-#define MAX_KEY 255 +-#define MAP_LEN (MAX_KEY - MIN_KEY + 1) +-#define KEYSYMS_PER_KEY 2 +-KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = { +- NoSymbol, NoSymbol, +- XK_Escape, NoSymbol, +- XK_1, XK_exclam, +- XK_2, XK_at, +- XK_3, XK_numbersign, +- XK_4, XK_dollar, +- XK_5, XK_percent, +- XK_6, XK_asciicircum, +- XK_7, XK_ampersand, +- XK_8, XK_asterisk, +- XK_9, XK_parenleft, +- XK_0, XK_parenright, +- XK_minus, XK_underscore, +- XK_equal, XK_plus, +- XK_BackSpace, NoSymbol, +- XK_Tab, NoSymbol, +- XK_q, XK_Q, +- XK_w, XK_W, +- XK_e, XK_E, +- XK_r, XK_R, +- XK_t, XK_T, +- XK_y, XK_Y, +- XK_u, XK_U, +- XK_i, XK_I, +- XK_o, XK_O, +- XK_p, XK_P, +- XK_bracketleft, XK_braceleft, +- XK_bracketright, XK_braceright, +- XK_Return, NoSymbol, +- XK_Control_L, NoSymbol, +- XK_a, XK_A, +- XK_s, XK_S, +- XK_d, XK_D, +- XK_f, XK_F, +- XK_g, XK_G, +- XK_h, XK_H, +- XK_j, XK_J, +- XK_k, XK_K, +- XK_l, XK_L, +- XK_semicolon, XK_colon, +- XK_apostrophe, XK_quotedbl, +- XK_grave, XK_asciitilde, +- XK_Shift_L, NoSymbol, +- XK_backslash, XK_bar, +- XK_z, XK_Z, +- XK_x, XK_X, +- XK_c, XK_C, +- XK_v, XK_V, +- XK_b, XK_B, +- XK_n, XK_N, +- XK_m, XK_M, +- XK_comma, XK_less, +- XK_period, XK_greater, +- XK_slash, XK_question, +- XK_Shift_R, NoSymbol, +- XK_KP_Multiply, NoSymbol, +- XK_Alt_L, XK_Meta_L, +- XK_space, NoSymbol, +- XK_Caps_Lock, NoSymbol, +- XK_F1, NoSymbol, +- XK_F2, NoSymbol, +- XK_F3, NoSymbol, +- XK_F4, NoSymbol, +- XK_F5, NoSymbol, +- XK_F6, NoSymbol, +- XK_F7, NoSymbol, +- XK_F8, NoSymbol, +- XK_F9, NoSymbol, +- XK_F10, NoSymbol, +- XK_Num_Lock, XK_Pointer_EnableKeys, +- XK_Scroll_Lock, NoSymbol, +- XK_KP_Home, XK_KP_7, +- XK_KP_Up, XK_KP_8, +- XK_KP_Prior, XK_KP_9, +- XK_KP_Subtract, NoSymbol, +- XK_KP_Left, XK_KP_4, +- XK_KP_Begin, XK_KP_5, +- XK_KP_Right, XK_KP_6, +- XK_KP_Add, NoSymbol, +- XK_KP_End, XK_KP_1, +- XK_KP_Down, XK_KP_2, +- XK_KP_Next, XK_KP_3, +- XK_KP_Insert, XK_KP_0, +- XK_KP_Delete, XK_KP_Decimal, +- NoSymbol, NoSymbol, +- NoSymbol, NoSymbol, +- NoSymbol, NoSymbol, +- XK_F11, NoSymbol, +- XK_F12, NoSymbol, +- XK_Home, NoSymbol, +- XK_Up, NoSymbol, +- XK_Prior, NoSymbol, +- XK_Left, NoSymbol, +- NoSymbol, NoSymbol, +- XK_Right, NoSymbol, +- XK_End, NoSymbol, +- XK_Down, NoSymbol, +- XK_Next, NoSymbol, +- XK_Insert, NoSymbol, +- XK_Delete, NoSymbol, +- XK_KP_Enter, NoSymbol, +- XK_Control_R, NoSymbol, +- XK_Pause, XK_Break, +- XK_Print, XK_Execute, +- XK_KP_Divide, NoSymbol, +- XK_Alt_R, XK_Meta_R, +- NoSymbol, NoSymbol, +- XK_Super_L, NoSymbol, +- XK_Super_R, NoSymbol, +- XK_Menu, NoSymbol, +-}; ++ pressKey(keyboardDev, level_three_press, true, "temp level 3 shift"); ++ } else if ((state & level_three_mask) && !(new_state & level_three_mask)) { ++ std::list::const_iterator iter; ++ ++ level_three_release = releaseLevelThree(); ++ if (level_three_release.empty()) { ++ vlog.error("Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch"); ++ return; ++ } + +-static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) +-{ +- int i; ++ for (iter = level_three_release.begin();iter != level_three_release.end();++iter) ++ pressKey(keyboardDev, *iter, false, "temp level 3 shift"); ++ } + +- for (i = 0; i < MAP_LENGTH; i++) +- pModMap[i] = NoSymbol; ++ /* Now press the actual key */ ++ pressKey(keyboardDev, keycode, true, "keycode"); + +- for (i = 0; i < MAP_LEN; i++) { +- switch (keyboardMap[i * KEYSYMS_PER_KEY]) { +- case XK_Shift_L: +- case XK_Shift_R: +- pModMap[i + MIN_KEY] = ShiftMask; +- break; +- case XK_Caps_Lock: +- pModMap[i + MIN_KEY] = LockMask; +- break; +- case XK_Control_L: +- case XK_Control_R: +- pModMap[i + MIN_KEY] = ControlMask; +- break; +- case XK_Alt_L: +- case XK_Alt_R: +- pModMap[i + MIN_KEY] = Mod1Mask; +- break; +- case XK_Num_Lock: +- pModMap[i + MIN_KEY] = Mod2Mask; +- break; +- /* No defaults for Mod3Mask yet */ +- case XK_Super_L: +- case XK_Super_R: +- case XK_Hyper_L: +- case XK_Hyper_R: +- pModMap[i + MIN_KEY] = Mod4Mask; +- break; +- case XK_ISO_Level3_Shift: +- case XK_Mode_switch: +- pModMap[i + MIN_KEY] = Mod5Mask; +- break; ++ /* 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) { ++ vlog.error("Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode); ++ pressedKeys[i] = NoSymbol; + } + } + +- pKeySyms->minKeyCode = MIN_KEY; +- pKeySyms->maxKeyCode = MAX_KEY; +- pKeySyms->mapWidth = KEYSYMS_PER_KEY; +- pKeySyms->map = keyboardMap; ++ pressedKeys[keycode] = keysym; + +- return TRUE; +-} +-#endif +- +-static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl, +- int class_) +-{ +- if (percent > 0) +- vncBell(); +-} +- +-static int keyboardProc(DeviceIntPtr pDevice, int onoff) +-{ +-#if XORG < 17 +- KeySymsRec keySyms; +- CARD8 modMap[MAP_LENGTH]; +-#endif +- DevicePtr pDev = (DevicePtr)pDevice; ++ /* Undo any fake level three shift */ ++ if (level_three_press != 0) ++ pressKey(keyboardDev, level_three_press, false, "temp level 3 shift"); ++ else if (!level_three_release.empty()) { ++ std::list::const_iterator iter; ++ for (iter = level_three_release.begin();iter != level_three_release.end();++iter) ++ pressKey(keyboardDev, *iter, true, "temp level 3 shift"); ++ } + +- switch (onoff) { +- case DEVICE_INIT: +-#if XORG < 17 +- GetMappings(&keySyms, modMap); +-#endif +- InitKeyboardDeviceStruct( +-#if XORG >= 17 +- pDevice, NULL, +-#else +- pDev, &keySyms, modMap, +-#endif +- keyboardBell, (KbdCtrlProcPtr)NoopDDA); +- break; +- case DEVICE_ON: +- pDev->on = TRUE; +- break; +- case DEVICE_OFF: +- pDev->on = FALSE; +- break; +-#if 0 +- case DEVICE_CLOSE: +- break; +-#endif ++ /* Undo any fake shift */ ++ if (shift_press != 0) ++ pressKey(keyboardDev, shift_press, false, "temp shift"); ++ else if (!shift_release.empty()) { ++ std::list::const_iterator iter; ++ for (iter = shift_release.begin();iter != shift_release.end();++iter) ++ pressKey(keyboardDev, *iter, true, "temp shift"); + } + +- return Success; ++ /* ++ * 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(); + } +- +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc.input 2014-01-17 16:01:13.141109454 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc 2014-01-17 16:01:13.141109454 +0000 +@@ -0,0 +1,594 @@ ++/* Copyright (C) 2009 TightVNC Team ++ * Copyright (C) 2009 Red Hat, Inc. ++ * Copyright 2013 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 ++#endif ++ ++#include "Input.h" ++#include "xorg-version.h" ++ ++extern "C" { ++#define public c_public ++#define class c_class ++#include "inputstr.h" ++#ifndef XKB_IN_SERVER ++#define XKB_IN_SERVER ++#endif ++#ifdef XKB ++/* ++ * This include is needed to use XkbConvertCase instead of XConvertCase even if ++ * we don't use XKB extension. ++ */ ++#include ++#endif ++/* These defines give us access to all keysyms we need */ ++#define XK_PUBLISHING ++#define XK_TECHNICAL ++#include ++#include ++#include ++#include ++#undef public ++#undef class ++} ++ ++#if XORG < 17 ++ ++#define IS_PRESSED(dev, keycode) \ ++ ((dev)->key->down[(keycode) >> 3] & (1 << ((keycode) & 7))) ++ ++/* Fairly standard US PC Keyboard */ ++ ++#define MIN_KEY 8 ++#define MAX_KEY 255 ++#define MAP_LEN (MAX_KEY - MIN_KEY + 1) ++#define KEYSYMS_PER_KEY 2 ++KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = { ++ NoSymbol, NoSymbol, ++ XK_Escape, NoSymbol, ++ XK_1, XK_exclam, ++ XK_2, XK_at, ++ XK_3, XK_numbersign, ++ XK_4, XK_dollar, ++ XK_5, XK_percent, ++ XK_6, XK_asciicircum, ++ XK_7, XK_ampersand, ++ XK_8, XK_asterisk, ++ XK_9, XK_parenleft, ++ XK_0, XK_parenright, ++ XK_minus, XK_underscore, ++ XK_equal, XK_plus, ++ XK_BackSpace, NoSymbol, ++ XK_Tab, NoSymbol, ++ XK_q, XK_Q, ++ XK_w, XK_W, ++ XK_e, XK_E, ++ XK_r, XK_R, ++ XK_t, XK_T, ++ XK_y, XK_Y, ++ XK_u, XK_U, ++ XK_i, XK_I, ++ XK_o, XK_O, ++ XK_p, XK_P, ++ XK_bracketleft, XK_braceleft, ++ XK_bracketright, XK_braceright, ++ XK_Return, NoSymbol, ++ XK_Control_L, NoSymbol, ++ XK_a, XK_A, ++ XK_s, XK_S, ++ XK_d, XK_D, ++ XK_f, XK_F, ++ XK_g, XK_G, ++ XK_h, XK_H, ++ XK_j, XK_J, ++ XK_k, XK_K, ++ XK_l, XK_L, ++ XK_semicolon, XK_colon, ++ XK_apostrophe, XK_quotedbl, ++ XK_grave, XK_asciitilde, ++ XK_Shift_L, NoSymbol, ++ XK_backslash, XK_bar, ++ XK_z, XK_Z, ++ XK_x, XK_X, ++ XK_c, XK_C, ++ XK_v, XK_V, ++ XK_b, XK_B, ++ XK_n, XK_N, ++ XK_m, XK_M, ++ XK_comma, XK_less, ++ XK_period, XK_greater, ++ XK_slash, XK_question, ++ XK_Shift_R, NoSymbol, ++ XK_KP_Multiply, NoSymbol, ++ XK_Alt_L, XK_Meta_L, ++ XK_space, NoSymbol, ++ XK_Caps_Lock, NoSymbol, ++ XK_F1, NoSymbol, ++ XK_F2, NoSymbol, ++ XK_F3, NoSymbol, ++ XK_F4, NoSymbol, ++ XK_F5, NoSymbol, ++ XK_F6, NoSymbol, ++ XK_F7, NoSymbol, ++ XK_F8, NoSymbol, ++ XK_F9, NoSymbol, ++ XK_F10, NoSymbol, ++ XK_Num_Lock, XK_Pointer_EnableKeys, ++ XK_Scroll_Lock, NoSymbol, ++ XK_KP_Home, XK_KP_7, ++ XK_KP_Up, XK_KP_8, ++ XK_KP_Prior, XK_KP_9, ++ XK_KP_Subtract, NoSymbol, ++ XK_KP_Left, XK_KP_4, ++ XK_KP_Begin, XK_KP_5, ++ XK_KP_Right, XK_KP_6, ++ XK_KP_Add, NoSymbol, ++ XK_KP_End, XK_KP_1, ++ XK_KP_Down, XK_KP_2, ++ XK_KP_Next, XK_KP_3, ++ XK_KP_Insert, XK_KP_0, ++ XK_KP_Delete, XK_KP_Decimal, ++ NoSymbol, NoSymbol, ++ NoSymbol, NoSymbol, ++ NoSymbol, NoSymbol, ++ XK_F11, NoSymbol, ++ XK_F12, NoSymbol, ++ XK_Home, NoSymbol, ++ XK_Up, NoSymbol, ++ XK_Prior, NoSymbol, ++ XK_Left, NoSymbol, ++ NoSymbol, NoSymbol, ++ XK_Right, NoSymbol, ++ XK_End, NoSymbol, ++ XK_Down, NoSymbol, ++ XK_Next, NoSymbol, ++ XK_Insert, NoSymbol, ++ XK_Delete, NoSymbol, ++ XK_KP_Enter, NoSymbol, ++ XK_Control_R, NoSymbol, ++ XK_Pause, XK_Break, ++ XK_Print, XK_Execute, ++ XK_KP_Divide, NoSymbol, ++ XK_Alt_R, XK_Meta_R, ++ NoSymbol, NoSymbol, ++ XK_Super_L, NoSymbol, ++ XK_Super_R, NoSymbol, ++ XK_Menu, NoSymbol, ++}; ++ ++void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap) ++{ ++ int i; ++ ++ for (i = 0; i < MAP_LENGTH; i++) ++ modmap[i] = NoSymbol; ++ ++ for (i = 0; i < MAP_LEN; i++) { ++ switch (keyboardMap[i * KEYSYMS_PER_KEY]) { ++ case XK_Shift_L: ++ case XK_Shift_R: ++ modmap[i + MIN_KEY] = ShiftMask; ++ break; ++ case XK_Caps_Lock: ++ modmap[i + MIN_KEY] = LockMask; ++ break; ++ case XK_Control_L: ++ case XK_Control_R: ++ modmap[i + MIN_KEY] = ControlMask; ++ break; ++ case XK_Alt_L: ++ case XK_Alt_R: ++ modmap[i + MIN_KEY] = Mod1Mask; ++ break; ++ case XK_Num_Lock: ++ modmap[i + MIN_KEY] = Mod2Mask; ++ break; ++ /* No defaults for Mod3Mask yet */ ++ case XK_Super_L: ++ case XK_Super_R: ++ case XK_Hyper_L: ++ case XK_Hyper_R: ++ modmap[i + MIN_KEY] = Mod4Mask; ++ break; ++ case XK_ISO_Level3_Shift: ++ case XK_Mode_switch: ++ modmap[i + MIN_KEY] = Mod5Mask; ++ break; ++ } ++ } ++ ++ keysyms->minKeyCode = MIN_KEY; ++ keysyms->maxKeyCode = MAX_KEY; ++ keysyms->mapWidth = KEYSYMS_PER_KEY; ++ keysyms->map = keyboardMap; ++} ++ ++void InputDevice::PrepareInputDevices(void) ++{ ++ /* Don't need to do anything here */ ++} ++ ++unsigned InputDevice::getKeyboardState(void) ++{ ++ return keyboardDev->key->state; ++} ++ ++unsigned InputDevice::getLevelThreeMask(void) ++{ ++ int i, j, k; ++ ++ int minKeyCode, mapWidth; ++ KeySym *map; ++ ++ int maxKeysPerMod; ++ CARD8 *modmap; ++ ++ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode; ++ mapWidth = keyboardDev->key->curKeySyms.mapWidth; ++ map = keyboardDev->key->curKeySyms.map; ++ ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ modmap = keyboardDev->key->modifierKeyMap; ++ ++ for (i = 3; i < 8; i++) { ++ for (k = 0; k < maxKeysPerMod; k++) { ++ int index = i * maxKeysPerMod + k; ++ int keycode = modmap[index]; ++ ++ if (keycode == 0) ++ continue; ++ ++ for (j = 0; j < mapWidth; j++) { ++ KeySym keysym; ++ keysym = map[(keycode - minKeyCode) * mapWidth + j]; ++ if (keysym == XK_Mode_switch) ++ return 1 << i; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++KeyCode InputDevice::pressShift(void) ++{ ++ int maxKeysPerMod; ++ ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ return keyboardDev->key->modifierKeyMap[ShiftMapIndex * maxKeysPerMod]; ++} ++ ++std::list InputDevice::releaseShift(void) ++{ ++ std::list keys; ++ ++ int maxKeysPerMod; ++ ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ for (int k = 0; k < maxKeysPerMod; k++) { ++ int keycode; ++ int index; ++ ++ index = ShiftMapIndex * maxKeysPerMod + k; ++ ++ keycode = keyboardDev->key->modifierKeyMap[index]; ++ if (keycode == 0) ++ continue; ++ ++ if (!IS_PRESSED(keyboardDev, keycode)) ++ continue; ++ ++ keys.push_back(keycode); ++ } ++ ++ return keys; ++} ++ ++KeyCode InputDevice::pressLevelThree(void) ++{ ++ unsigned mask, index; ++ int maxKeysPerMod; ++ ++ mask = getLevelThreeMask(); ++ if (mask == 0) ++ return 0; ++ ++ index = ffs(mask) - 1; ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ return keyboardDev->key->modifierKeyMap[index * maxKeysPerMod]; ++} ++ ++std::list InputDevice::releaseLevelThree(void) ++{ ++ std::list keys; ++ ++ unsigned mask, msindex; ++ int maxKeysPerMod; ++ ++ mask = getLevelThreeMask(); ++ if (mask == 0) ++ return keys; ++ ++ msindex = ffs(mask) - 1; ++ ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ for (int k = 0; k < maxKeysPerMod; k++) { ++ int keycode; ++ int index; ++ ++ index = msindex * maxKeysPerMod + k; ++ ++ keycode = keyboardDev->key->modifierKeyMap[index]; ++ if (keycode == 0) ++ continue; ++ ++ if (!IS_PRESSED(keyboardDev, keycode)) ++ continue; ++ ++ keys.push_back(keycode); ++ } ++ ++ return keys; ++} ++ ++static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) ++{ ++ int per = keymap->mapWidth; ++ KeySym *syms; ++ KeySym lsym, usym; ++ ++ if ((col < 0) || ((col >= per) && (col > 3)) || ++ (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) ++ return NoSymbol; ++ ++ syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; ++ if (col >= 4) ++ return syms[col]; ++ ++ if (col > 1) { ++ while ((per > 2) && (syms[per - 1] == NoSymbol)) ++ per--; ++ if (per < 3) ++ col -= 2; ++ } ++ ++ if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { ++ XkbConvertCase(syms[col&~1], &lsym, &usym); ++ if (!(col & 1)) ++ return lsym; ++ /* ++ * I'm commenting out this logic because it's incorrect even ++ * though it was copied from the Xlib sources. The X protocol ++ * book quite clearly states that where a group consists of ++ * element 1 being a non-alphabetic keysym and element 2 being ++ * NoSymbol that you treat the second element as being the ++ * same as the first. This also tallies with the behaviour ++ * produced by the installed Xlib on my linux box (I believe ++ * this is because it uses some XKB code rather than the ++ * original Xlib code - compare XKBBind.c with KeyBind.c in ++ * lib/X11). ++ */ ++#if 0 ++ else if (usym == lsym) ++ return NoSymbol; ++#endif ++ else ++ return usym; ++ } ++ ++ return syms[col]; ++} ++ ++KeyCode InputDevice::keysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state) ++{ ++ int i, j; ++ unsigned mask; ++ ++ KeySymsPtr keymap; ++ int mapWidth; ++ ++ mask = getLevelThreeMask(); ++ ++ keymap = &keyboardDev->key->curKeySyms; ++ ++ /* ++ * Column 0 means both shift and "mode_switch" (AltGr) must be released, ++ * column 1 means shift must be pressed and mode_switch released, ++ * column 2 means shift must be released and mode_switch pressed, and ++ * column 3 means both shift and mode_switch must be pressed. ++ */ ++ j = 0; ++ if (state & ShiftMask) ++ j |= 0x1; ++ if (state & mask) ++ j |= 0x2; ++ ++ *new_state = state; ++ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { ++ if (KeyCodetoKeySym(keymap, i, j) == keysym) ++ return i; ++ } ++ ++ /* Only the first four columns have well-defined meaning */ ++ mapWidth = keymap->mapWidth; ++ if (mapWidth > 4) ++ mapWidth = 4; ++ ++ for (j = 0; j < mapWidth; j++) { ++ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { ++ if (KeyCodetoKeySym(keymap, i, j) == keysym) { ++ *new_state = state & ~(ShiftMask|mask); ++ if (j & 0x1) ++ *new_state |= ShiftMask; ++ if (j & 0x2) ++ *new_state |= mask; ++ ++ return i; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++bool InputDevice::isLockModifier(KeyCode keycode, unsigned state) ++{ ++ int i, j, k; ++ ++ int minKeyCode, mapWidth; ++ KeySym *map; ++ ++ int maxKeysPerMod; ++ CARD8 *modmap; ++ ++ int num_lock_index; ++ ++ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode; ++ mapWidth = keyboardDev->key->curKeySyms.mapWidth; ++ map = keyboardDev->key->curKeySyms.map; ++ ++ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier; ++ modmap = keyboardDev->key->modifierKeyMap; ++ ++ /* Caps Lock is fairly easy as it has a dedicated modmap entry */ ++ for (k = 0; k < maxKeysPerMod; k++) { ++ int index; ++ ++ index = LockMapIndex * maxKeysPerMod + k; ++ if (keycode == modmap[index]) ++ return true; ++ } ++ ++ /* For Num Lock we need to find the correct modmap entry */ ++ num_lock_index = i; ++ for (i = 3; i < 8; i++) { ++ for (k = 0; k < maxKeysPerMod; k++) { ++ int index = i * maxKeysPerMod + k; ++ int keycode = modmap[index]; ++ ++ if (keycode == 0) ++ continue; ++ ++ for (j = 0; j < mapWidth; j++) { ++ KeySym keysym; ++ keysym = map[(keycode - minKeyCode) * mapWidth + j]; ++ if (keysym == XK_Num_Lock) { ++ num_lock_index = i; ++ goto done; ++ } ++ } ++ } ++ } ++done: ++ ++ if (num_lock_index == 0) ++ return false; ++ ++ /* Now we can look in the modmap */ ++ for (k = 0; k < maxKeysPerMod; k++) { ++ int index; ++ ++ index = num_lock_index * maxKeysPerMod + k; ++ if (keycode == modmap[index]) ++ return true; ++ } ++ ++ return false; ++} ++ ++bool InputDevice::isAffectedByNumLock(KeyCode keycode) ++{ ++ KeySymsPtr keymap; ++ int i, per; ++ KeySym *syms; ++ ++ keymap = &keyboardDev->key->curKeySyms; ++ per = keymap->mapWidth; ++ syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; ++ ++ for (i = 0;i < per;i++) { ++ if (IsKeypadKey(syms[i])) ++ return true; ++ if (IsPrivateKeypadKey(syms[i])) ++ return true; ++ } ++ ++ return false; ++} ++ ++KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state) ++{ ++ KeyCode kc; ++ ++ int minKeyCode, maxKeyCode, mapWidth; ++ KeySym *map; ++ ++ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode; ++ maxKeyCode = keyboardDev->key->curKeySyms.maxKeyCode; ++ mapWidth = keyboardDev->key->curKeySyms.mapWidth; ++ map = keyboardDev->key->curKeySyms.map; ++ ++ /* ++ * Magic, which dynamically adds keysym<->keycode mapping ++ * depends on X.Org version. Quick explanation of that "magic": ++ * ++ * 1.5 ++ * - has only one core keyboard so we have to keep core ++ * keyboard mapping synchronized with vncKeyboardDevice. Do ++ * it via SwitchCoreKeyboard() ++ * ++ * 1.6 (aka MPX - Multi pointer X) ++ * - multiple master devices (= core devices) exists, keep ++ * vncKeyboardDevice synchronized with proper master device ++ */ ++ for (kc = maxKeyCode; kc >= minKeyCode; kc--) { ++ DeviceIntPtr master; ++ ++ if (map[(kc - minKeyCode) * mapWidth] != 0) ++ continue; ++ ++ map[(kc - minKeyCode) * mapWidth] = keysym; ++ ++#if XORG == 15 ++ master = inputInfo.keyboard; ++#else ++ master = keyboardDev->u.master; ++#endif ++ void *slave = dixLookupPrivate(&master->devPrivates, ++ CoreDevicePrivateKey); ++ if (keyboardDev == slave) { ++ dixSetPrivate(&master->devPrivates, ++ CoreDevicePrivateKey, NULL); ++#if XORG == 15 ++ SwitchCoreKeyboard(keyboardDev); ++#else ++ CopyKeyClass(keyboardDev, master); ++#endif ++ } ++ ++ return kc; ++ } ++ ++ return 0; ++} ++ ++#endif ++ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h.input 2010-04-14 10:24:06.000000000 +0100 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h 2014-01-17 16:01:13.141109454 +0000 +@@ -1,6 +1,7 @@ + /* Copyright (C) 2009 TightVNC Team + * Copyright (C) 2009, 2010 Red Hat, Inc. + * Copyright (C) 2009, 2010 TigerVNC Team ++ * Copyright 2013 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 +@@ -26,12 +27,16 @@ + #include + #endif + ++#include ++ + #include + + extern "C" { + #include "input.h" + }; + ++#include "xorg-version.h" ++ + /* Represents input device (keyboard + pointer) */ + class InputDevice { + public: +@@ -55,24 +60,58 @@ public: + + void KeyboardPress(rdr::U32 keysym) { keyEvent(keysym, true); } + void KeyboardRelease(rdr::U32 keysym) { keyEvent(keysym, false); } +-private: ++ + /* + * Init input device. This cannot be done in the constructor + * because constructor is called during X server extensions + * initialization. Devices must be initialized after core + * pointer/keyboard initialization which is actually after extesions + * initialization. Check InitExtensions(), InitCoreDevices() and +- * InitInput() calls in dix/main.c ++ * InitInput() calls in dix/main.c. Instead it is called from ++ * XserverDesktop at an appropriate time. + */ +- void initInputDevice(void); ++ void InitInputDevice(void); + ++private: + void keyEvent(rdr::U32 keysym, bool down); + ++ /* Backend dependent functions below here */ ++ void PrepareInputDevices(void); ++ ++ unsigned getKeyboardState(void); ++ unsigned getLevelThreeMask(void); ++ ++ KeyCode pressShift(void); ++ std::list releaseShift(void); ++ ++ KeyCode pressLevelThree(void); ++ std::list releaseLevelThree(void); ++ ++ KeyCode keysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state); ++ ++ bool isLockModifier(KeyCode keycode, unsigned state); ++ ++ bool isAffectedByNumLock(KeyCode keycode); ++ ++ KeyCode addKeysym(KeySym keysym, unsigned state); ++ ++private: ++#if XORG >= 17 ++ static void vncXkbProcessDeviceEvent(int screenNum, ++ InternalEvent *event, ++ DeviceIntPtr dev); ++#endif ++ ++private: + rfb::VNCServerST *server; ++ bool initialized; + DeviceIntPtr keyboardDev; + DeviceIntPtr pointerDev; ++ + int oldButtonMask; + rfb::Point cursorPos, oldCursorPos; ++ ++ KeySym pressedKeys[256]; + }; + + #endif +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc.input 2014-01-17 16:01:13.141109454 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc 2014-01-17 16:01:13.141109454 +0000 +@@ -0,0 +1,669 @@ ++/* Copyright (C) 2009 TightVNC Team ++ * Copyright (C) 2009 Red Hat, Inc. ++ * Copyright 2013 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 ++#endif ++ ++#include "Input.h" ++#include "xorg-version.h" ++ ++#if XORG >= 17 ++ ++extern "C" { ++#define public c_public ++#define class c_class ++#include "xkbsrv.h" ++#include "xkbstr.h" ++#include "eventstr.h" ++#include "scrnintstr.h" ++#include "mi.h" ++#include ++#include ++#include ++#undef public ++#undef class ++} ++ ++#if XORG < 19 ++static int vncXkbScreenPrivateKeyIndex; ++static DevPrivateKey vncXkbScreenPrivateKey = &vncXkbScreenPrivateKeyIndex; ++#else ++static DevPrivateKeyRec vncXkbPrivateKeyRec; ++#define vncXkbScreenPrivateKey (&vncXkbPrivateKeyRec) ++#endif ++ ++#define vncXkbScreenPrivate(pScreen) \ ++ (*(InputDevice**) dixLookupPrivate(&(pScreen)->devPrivates, \ ++ vncXkbScreenPrivateKey)) ++ ++#ifndef KEYBOARD_OR_FLOAT ++#define KEYBOARD_OR_FLOAT MASTER_KEYBOARD ++#endif ++ ++/* 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;imap_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;imap_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 InputDevice::PrepareInputDevices(void) ++{ ++#if XORG < 19 ++ if (!dixRequestPrivate(vncXkbScreenPrivateKey, sizeof(InputDevice*))) ++ FatalError("Failed to register TigerVNC XKB screen key\n"); ++#else ++ if (!dixRegisterPrivateKey(vncXkbScreenPrivateKey, PRIVATE_SCREEN, ++ sizeof(InputDevice*))) ++ FatalError("Failed to register TigerVNC XKB screen key\n"); ++#endif ++ ++ for (int scr = 0; scr < screenInfo.numScreens; scr++) ++ vncXkbScreenPrivate(screenInfo.screens[scr]) = this; ++ ++ /* ++ * 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 InputDevice::getKeyboardState(void) ++{ ++ return XkbStateFieldFromRec(&keyboardDev->master->key->xkbInfo->state); ++} ++ ++unsigned InputDevice::getLevelThreeMask(void) ++{ ++ unsigned state; ++ KeyCode keycode; ++ XkbDescPtr xkb; ++ XkbAction *act; ++ ++ /* Group state is still important */ ++ state = getKeyboardState(); ++ state &= ~0xff; ++ ++ keycode = keysymToKeycode(XK_ISO_Level3_Shift, state, NULL); ++ if (keycode == 0) { ++ keycode = keysymToKeycode(XK_Mode_switch, state, NULL); ++ if (keycode == 0) ++ return 0; ++ } ++ ++ xkb = keyboardDev->master->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 InputDevice::pressShift(void) ++{ ++ unsigned state; ++ ++ XkbDescPtr xkb; ++ unsigned int key; ++ ++ state = getKeyboardState(); ++ if (state & ShiftMask) ++ return 0; ++ ++ xkb = keyboardDev->master->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; ++} ++ ++std::list InputDevice::releaseShift(void) ++{ ++ unsigned state; ++ std::list keys; ++ ++ DeviceIntPtr master; ++ XkbDescPtr xkb; ++ unsigned int key; ++ ++ state = getKeyboardState(); ++ if (!(state & ShiftMask)) ++ return keys; ++ ++ master = keyboardDev->master; ++ 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; ++ ++ keys.push_back(key); ++ } ++ ++ return keys; ++} ++ ++KeyCode InputDevice::pressLevelThree(void) ++{ ++ unsigned state, mask; ++ ++ KeyCode keycode; ++ XkbDescPtr xkb; ++ XkbAction *act; ++ ++ mask = getLevelThreeMask(); ++ if (mask == 0) ++ return 0; ++ ++ state = getKeyboardState(); ++ if (state & mask) ++ return 0; ++ ++ keycode = keysymToKeycode(XK_ISO_Level3_Shift, state, NULL); ++ if (keycode == 0) { ++ keycode = keysymToKeycode(XK_Mode_switch, state, NULL); ++ if (keycode == 0) ++ return 0; ++ } ++ ++ xkb = keyboardDev->master->key->xkbInfo->desc; ++ ++ act = XkbKeyActionPtr(xkb, keycode, state); ++ if (act == NULL) ++ return 0; ++ if (act->type != XkbSA_SetMods) ++ return 0; ++ ++ return keycode; ++} ++ ++std::list InputDevice::releaseLevelThree(void) ++{ ++ unsigned state, mask; ++ std::list keys; ++ ++ DeviceIntPtr master; ++ XkbDescPtr xkb; ++ unsigned int key; ++ ++ mask = getLevelThreeMask(); ++ if (mask == 0) ++ return keys; ++ ++ state = getKeyboardState(); ++ if (!(state & mask)) ++ return keys; ++ ++ master = keyboardDev->master; ++ 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; ++ ++ keys.push_back(key); ++ } ++ ++ return keys; ++} ++ ++KeyCode InputDevice::keysymToKeycode(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 = keyboardDev->master->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 = keysymToKeycode(keysym, *new_state, NULL); ++ if (key != 0) ++ return key; ++ ++ level_three_mask = getLevelThreeMask(); ++ if (level_three_mask == 0) ++ return 0; ++ ++ *new_state = (state & ~level_three_mask) | ++ ((state & level_three_mask) ? 0 : level_three_mask); ++ key = keysymToKeycode(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 = keysymToKeycode(keysym, *new_state, NULL); ++ if (key != 0) ++ return key; ++ ++ return 0; ++} ++ ++bool InputDevice::isLockModifier(KeyCode keycode, unsigned state) ++{ ++ XkbDescPtr xkb; ++ XkbAction *act; ++ ++ xkb = keyboardDev->master->key->xkbInfo->desc; ++ ++ act = XkbKeyActionPtr(xkb, keycode, state); ++ if (act == NULL) ++ return false; ++ ++ if (act->type != XkbSA_LockMods) ++ return false; ++ ++ return true; ++} ++ ++bool InputDevice::isAffectedByNumLock(KeyCode keycode) ++{ ++ unsigned state; ++ ++ KeyCode numlock_keycode; ++ unsigned numlock_mask; ++ ++ XkbDescPtr xkb; ++ XkbAction *act; ++ ++ unsigned group; ++ XkbKeyTypeRec *type; ++ ++ /* Group state is still important */ ++ state = getKeyboardState(); ++ 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 = keysymToKeycode(XK_Num_Lock, state, NULL); ++ if (numlock_keycode == 0) ++ return false; ++ ++ xkb = keyboardDev->master->key->xkbInfo->desc; ++ ++ act = XkbKeyActionPtr(xkb, numlock_keycode, state); ++ if (act == NULL) ++ return false; ++ if (act->type != XkbSA_LockMods) ++ return false; ++ ++ 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 false; ++ ++ return true; ++} ++ ++KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state) ++{ ++ DeviceIntPtr master; ++ XkbDescPtr xkb; ++ unsigned int key; ++ ++ XkbEventCauseRec cause; ++ XkbChangesRec changes; ++ ++ int types[1]; ++ KeySym *syms; ++ KeySym upper, lower; ++ ++ master = keyboardDev->master; ++ 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; ++} ++ ++void InputDevice::vncXkbProcessDeviceEvent(int screenNum, ++ InternalEvent *event, ++ DeviceIntPtr dev) ++{ ++ InputDevice *self = vncXkbScreenPrivate(screenInfo.screens[screenNum]); ++ unsigned int backupctrls; ++ ++ if (event->device_event.sourceid == self->keyboardDev->id) { ++ XkbControlsPtr ctrls; ++ ++ /* ++ * 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->c_public.processInputProc(event, dev); ++ ++ if (event->device_event.sourceid == self->keyboardDev->id) { ++ XkbControlsPtr ctrls; ++ ++ ctrls = dev->key->xkbInfo->desc->ctrls; ++ ctrls->enabled_ctrls = backupctrls; ++ } ++} ++ ++#endif /* XORG >= 117 */ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am.input 2014-01-17 16:01:04.154064515 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am 2014-01-17 16:01:13.142109459 +0000 +@@ -14,7 +14,7 @@ HDRS = RegionHelper.h vncExtInit.h vncHo + Input.h + + libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \ +- Input.cc ++ Input.cc InputCore.cc InputXKB.cc + + libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \ + -DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(TIGERVNC_SRCDIR)/common -UHAVE_CONFIG_H \ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.input 2014-01-17 16:01:32.532206349 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc 2014-01-17 16:02:13.775412129 +0000 +@@ -579,6 +579,12 @@ static struct timeval XserverDesktopTime + + void XserverDesktop::blockHandler(fd_set* fds, OSTimePtr 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. ++ inputDevice->InitInputDevice(); ++ + try { + int nextTimeout; + diff --git a/SOURCES/tigervnc-manpages.patch b/SOURCES/tigervnc-manpages.patch new file mode 100644 index 0000000..7acf128 --- /dev/null +++ b/SOURCES/tigervnc-manpages.patch @@ -0,0 +1,236 @@ +diff -up tigervnc-1.2.80-20130314svn5065/unix/vncserver.man.manpages tigervnc-1.2.80-20130314svn5065/unix/vncserver.man +--- tigervnc-1.2.80-20130314svn5065/unix/vncserver.man.manpages 2013-07-03 12:44:03.820392690 +0100 ++++ tigervnc-1.2.80-20130314svn5065/unix/vncserver.man 2013-07-03 12:44:44.222587028 +0100 +@@ -92,6 +92,10 @@ argument. Thus, you can invoke "vncserv + end of your xstartup file after a particular application exits. + + .TP ++.B \-list ++Lists running VNC servers. ++ ++.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. +diff -up tigervnc-1.2.80-20130314svn5065/unix/vncserver.manpages tigervnc-1.2.80-20130314svn5065/unix/vncserver +--- tigervnc-1.2.80-20130314svn5065/unix/vncserver.manpages 2013-07-03 12:39:08.754980784 +0100 ++++ tigervnc-1.2.80-20130314svn5065/unix/vncserver 2013-07-03 12:43:57.932364387 +0100 +@@ -551,6 +551,7 @@ sub Usage + " [-geometry x]\n". + " [-pixelformat rgbNNN|bgrNNN]\n". + " [-fp ]\n". ++ " [-cc ]\n". + " [-fg]\n". + " [-autokill]\n". + " ...\n\n". +diff -up tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.cxx.manpages tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.cxx +diff -up tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.man.manpages tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.man +--- tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.man.manpages 2013-07-03 12:46:17.814038117 +0100 ++++ tigervnc-1.2.80-20130314svn5065/unix/x0vncserver/x0vncserver.man 2013-07-03 12:58:32.814621597 +0100 +@@ -68,7 +68,13 @@ to accept connections from any IP addres + Specify which security scheme to use for incoming connections. Valid values + are \fBNone\fP and \fBVncAuth\fP. Default is \fBVncAuth\fP. + .TP +-.B PasswordFile ++.B pam_server ++Service name for pam password validation (default is "vnc"). ++.TP ++.B PlainUsers ++Users permission to access via Plain security type. ++.TP ++.B PasswordFile, rfbauth + 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. +@@ -113,6 +119,16 @@ Accept key press and release events from + .B AcceptPointerEvents + Accept pointer events from clients. Default is on. + .TP ++.B AcceptCutText ++Accept clipboard updates from clients. Default is on. ++.TP ++.B MaxCutText ++Maximum permitted length of an incoming clipboard update (default is ++262144). ++.TP ++.B SendCutText ++Send clipboard changes to clients. Default is on. ++.TP + .B RemapKeys + Comma-separated list of incoming keysyms to remap. Mappings are expressed as + two hex values, prefixed by \fB0x\fP, and separated by \fB->\fP (`dash' and +@@ -154,23 +170,6 @@ clients may choose video selection thems + \fBVideoArea\fP parameter will take effect. If the argument is empty, no + video area is set (this is the default). + .TP +-.B VideoPriority +-Specify the priority of sending video updates. \fBx0vncserver\fP can be +-instructed to treat certain rectangular part of the screen as a video area +-and handle it in a special way for improved performance (see documentation on +-the \fBVideoArea\fP parameter). \fBVideoPriority\fP value controls how often +-video area will be sent to clients as compared to the rest of the screen. +-The priority must be an integer between 0 and 8, and the default value is 2. +- +-\fBVideoPriority\fP set to 1 gives the same priority both to video and to +-other pixels. Higher values give more priority to video. For example, the +-value 5 specifies that the rate of sending video will be five times higher +-than the rate of updating the rest of the screen. If \fBVideoPriority\fP is +-set to 0, it gives equal priority to video and other updates (just like the +-value 1) and also disables special encoding for video data. In other words, +-\fBVideoPriority\fP video area will be sent as a part of other screen +-contents. +-.TP + .B CompareFB + Perform pixel comparison on framebuffer to reduce unnecessary updates. + Default is on. +@@ -185,15 +184,6 @@ This enables system-specific access to c + screen (the default X visual often provides 256 colors). Also, in overlay + mode, \fBx0vncserver\fP can show correct mouse cursor. Default is on. + .TP +-.B UseHardwareJPEG +-Use hardware-accelerated JPEG compressor for video if available. +-\fBx0vncserver\fP can be instructed to treat certain rectangular part of the +-screen as a video area and handle it in a special way for improved +-performance. If the client supports Tight encoding and JPEG compression, +-such video areas will be sent as JPEG-encoded rectangles. And if this option +-is on, compression will be hardware-accelerated (currently, supported only in +-SGI/IRIX equipped with appropriate hardware). Default is on. +-.TP + .B ZlibLevel + Zlib compression level for ZRLE encoding (it does not affect Tight encoding). + Acceptable values are between 0 and 9. Default is to use the standard +@@ -222,6 +212,18 @@ Terminate after \fIN\fP seconds of user + .B ClientWaitTimeMillis + The number of milliseconds to wait for a client which is no longer + responding. Default is 20000. ++.TP ++.B DeferUpdate ++Time in milliseconds to defer updates (default is 1). ++.TP ++.B AlwaysSetDeferUpdateTimer ++Always reset the defer update timer on every change. ++.TP ++.B x509key ++Path to key of the x509 certificate in PEM format. ++.TP ++.B 509cert ++Path to x509 certificate in PEM format. + .SH SEE ALSO + .BR Xvnc (1), + .BR vncpasswd (1), +diff -up tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.cxx.manpages tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.cxx +--- tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.cxx.manpages 2013-07-03 12:00:58.005856116 +0100 ++++ tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.cxx 2013-07-03 12:04:26.083023050 +0100 +@@ -261,6 +261,11 @@ static void usage(const char *programNam + " %s [parameters] -listen [port] [parameters]\n", + programName, programName); + fprintf(stderr,"\n" ++ "Options:\n\n" ++ " -display Xdisplay - Specifies the X display for the viewer window\n" ++ " -geometry geometry - Standard X position and sizing specification.\n"); ++ ++ fprintf(stderr,"\n" + "Parameters can be turned on with - or off with -=0\n" + "Parameters which take a value can be specified as " + "- \n" +diff -up tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.man.manpages tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.man +--- tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.man.manpages 2013-07-03 11:40:48.905078300 +0100 ++++ tigervnc-1.2.80-20130314svn5065/vncviewer/vncviewer.man 2013-07-03 12:00:13.116604372 +0100 +@@ -113,12 +113,53 @@ Xvnc supports reverse connections with a + .B vncconfig. + + .TP +-.B \-passwd \fIpassword-file\fP ++.B \-passwd \fIpassword-file\fP, \-PasswordFile \fIpassword-file\fP + If you are on a filesystem which gives you access to the password file used by + the server, you can specify it here to avoid typing it in. It will usually be + "~/.vnc/passwd". + + .TP ++.B \-DotWhenNoCursor ++Show the dot cursor when the server sends an invisible cursor. ++ ++.TP ++.B \-PointerEventInterval ++Time in milliseconds to rate-limit successive pointer events. ++ ++.TP ++.B \-ImprovedHextile ++Try harder to compress data (default). ++ ++.TP ++.B \-QualityLevel \fIlevel\fP ++JPEG quality level (default is 8). ++ ++.TP ++.B \-NoJPEG ++Disable lossy JPEG compression in Tight encoding. ++ ++.TP ++.B CompressLevel \fIlevel\fP ++Use specified compression level (default is 2). ++ ++.TP ++.B CustomCompressLevel \fIlevel\fP ++Use custom compression level. Default is CompressLevel is specified. ++ ++.TP ++.B \-SendPrimary ++Send the primary selection and cut buffer to the server as well as the ++clipboard selection (default). ++ ++.TP ++.B \-SendClipboard ++Send clipboard changes to the server (default). ++ ++.TP ++.B \-AcceptClipboard ++Accept clipboard changes from the server (default). ++ ++.TP + .B \-Shared + When you make a connection to a VNC server, all other existing connections are + normally closed. This option requests that they be left open, allowing you to +@@ -140,6 +181,19 @@ Maximize viewer window. + Start in full-screen mode. + + .TP ++.B \-FullScreenAllMonitors ++Enable full screen over all monitors (default). ++ ++.TP ++.B \-FullscreenSystemKeys ++Pass special keys directly to the server in full-screen mode. ++ ++.TP ++.B \-RemoteResize ++Dynamically resize the remote desktop size as the size of the local ++client window changes (default). ++ ++.TP + .B \-DesktopSize \fIwidth\fPx\fIheight\fP + Instead of keeping the existing remote screen size, the client will attempt to + switch to the specified since when connecting. If the server does not support +@@ -214,6 +268,22 @@ command is executed with the environment + host, the port number on the remote host, and the gateway machine + respectively. + ++.TP ++\fB\-ZlibLevel\fR \fIlevel\fR ++Zlib compression level. ++ ++.TP ++.B \-x509crl \fIfile\fP ++X509 CRL file ++ ++.TP ++.B \-x509ca \fIfile\fP ++X509 CA certificate ++ ++.TP ++.B \-SecurityTypes \fItypes\fP ++Specify which security scheme to use. ++ + .SH SEE ALSO + .BR Xvnc (1), + .BR vncpasswd (1), diff --git a/SOURCES/tigervnc-setcursor-crash.patch b/SOURCES/tigervnc-setcursor-crash.patch new file mode 100644 index 0000000..1efbd0e --- /dev/null +++ b/SOURCES/tigervnc-setcursor-crash.patch @@ -0,0 +1,13 @@ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.jx tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.jx 2012-08-27 09:02:47.000000000 -0400 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc 2013-06-17 09:42:14.310725996 -0400 +@@ -479,6 +479,9 @@ void XserverDesktop::setCursor(CursorPtr + } + } else { + #endif ++ if (!cmap) ++ return; ++ + xColorItem fg, bg; + fg.red = cursor->foreRed; + fg.green = cursor->foreGreen; diff --git a/SOURCES/tigervnc-shebang.patch b/SOURCES/tigervnc-shebang.patch new file mode 100644 index 0000000..f76af87 --- /dev/null +++ b/SOURCES/tigervnc-shebang.patch @@ -0,0 +1,9 @@ +diff -up tigervnc-1.3.0/unix/vncserver.shebang tigervnc-1.3.0/unix/vncserver +--- tigervnc-1.3.0/unix/vncserver.shebang 2013-07-24 12:22:34.962158378 +0100 ++++ tigervnc-1.3.0/unix/vncserver 2013-07-24 12:22:41.593188190 +0100 +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + # + # Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. + # Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. diff --git a/SOURCES/tigervnc-xstartup.patch b/SOURCES/tigervnc-xstartup.patch new file mode 100644 index 0000000..696d92b --- /dev/null +++ b/SOURCES/tigervnc-xstartup.patch @@ -0,0 +1,32 @@ +diff -up tigervnc-1.3.0/unix/vncserver.xstartup tigervnc-1.3.0/unix/vncserver +--- tigervnc-1.3.0/unix/vncserver.xstartup 2014-02-10 14:52:39.902673875 +0000 ++++ tigervnc-1.3.0/unix/vncserver 2014-02-10 14:53:30.398847723 +0000 +@@ -59,27 +59,7 @@ $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"); ++ "exec /etc/X11/xinit/xinitrc\n"); + + chop($host = `uname -n`); + diff --git a/SOURCES/tigervnc-zrle-crash.patch b/SOURCES/tigervnc-zrle-crash.patch new file mode 100644 index 0000000..74545d7 --- /dev/null +++ b/SOURCES/tigervnc-zrle-crash.patch @@ -0,0 +1,69 @@ +diff -up tigervnc-1.3.0/common/rfb/ZRLEEncoder.cxx.zrle-crash tigervnc-1.3.0/common/rfb/ZRLEEncoder.cxx +--- tigervnc-1.3.0/common/rfb/ZRLEEncoder.cxx.zrle-crash 2013-07-01 13:41:59.000000000 +0100 ++++ tigervnc-1.3.0/common/rfb/ZRLEEncoder.cxx 2013-12-12 17:30:48.510007365 +0000 +@@ -55,16 +55,19 @@ Encoder* ZRLEEncoder::create(SMsgWriter* + } + + ZRLEEncoder::ZRLEEncoder(SMsgWriter* writer_) +- : writer(writer_), zos(0,0,zlibLevel) ++ : writer(writer_) + { + if (sharedMos) + mos = sharedMos; + else + mos = new rdr::MemOutStream(129*1024); ++ ++ zos = new rdr::ZlibOutStream(0, 0, zlibLevel); + } + + ZRLEEncoder::~ZRLEEncoder() + { ++ delete zos; + if (!sharedMos) + delete mos; + } +@@ -78,10 +81,10 @@ bool ZRLEEncoder::writeRect(const Rect& + + switch (writer->bpp()) { + case 8: +- wroteAll = zrleEncode8(r, mos, &zos, imageBuf, maxLen, actual, ig); ++ wroteAll = zrleEncode8(r, mos, zos, imageBuf, maxLen, actual, ig); + break; + case 16: +- wroteAll = zrleEncode16(r, mos, &zos, imageBuf, maxLen, actual, ig); ++ wroteAll = zrleEncode16(r, mos, zos, imageBuf, maxLen, actual, ig); + break; + case 32: + { +@@ -94,16 +97,16 @@ bool ZRLEEncoder::writeRect(const Rect& + if ((fitsInLS3Bytes && pf.isLittleEndian()) || + (fitsInMS3Bytes && pf.isBigEndian())) + { +- wroteAll = zrleEncode24A(r, mos, &zos, imageBuf, maxLen, actual, ig); ++ wroteAll = zrleEncode24A(r, mos, zos, imageBuf, maxLen, actual, ig); + } + else if ((fitsInLS3Bytes && pf.isBigEndian()) || + (fitsInMS3Bytes && pf.isLittleEndian())) + { +- wroteAll = zrleEncode24B(r, mos, &zos, imageBuf, maxLen, actual, ig); ++ wroteAll = zrleEncode24B(r, mos, zos, imageBuf, maxLen, actual, ig); + } + else + { +- wroteAll = zrleEncode32(r, mos, &zos, imageBuf, maxLen, actual, ig); ++ wroteAll = zrleEncode32(r, mos, zos, imageBuf, maxLen, actual, ig); + } + break; + } +diff -up tigervnc-1.3.0/common/rfb/ZRLEEncoder.h.zrle-crash tigervnc-1.3.0/common/rfb/ZRLEEncoder.h +--- tigervnc-1.3.0/common/rfb/ZRLEEncoder.h.zrle-crash 2013-07-01 13:42:01.000000000 +0100 ++++ tigervnc-1.3.0/common/rfb/ZRLEEncoder.h 2013-12-12 17:30:48.510007365 +0000 +@@ -45,7 +45,7 @@ namespace rfb { + private: + ZRLEEncoder(SMsgWriter* writer); + SMsgWriter* writer; +- rdr::ZlibOutStream zos; ++ rdr::ZlibOutStream* zos; + rdr::MemOutStream* mos; + static rdr::MemOutStream* sharedMos; + static int maxLen; diff --git a/SOURCES/tigervnc11-gethomedir.patch b/SOURCES/tigervnc11-gethomedir.patch new file mode 100644 index 0000000..0a4252d --- /dev/null +++ b/SOURCES/tigervnc11-gethomedir.patch @@ -0,0 +1,20 @@ +diff -up tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am.gethomedir tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am +--- tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am.gethomedir 2012-08-22 15:52:01.876216608 +0200 ++++ tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am 2012-08-22 15:52:45.973143684 +0200 +@@ -5,6 +5,7 @@ RFB_LIB=$(LIB_DIR)/rfb/librfb.la + RDR_LIB=$(LIB_DIR)/rdr/librdr.la + NETWORK_LIB=$(LIB_DIR)/network/libnetwork.la + XREGION_LIB=$(LIB_DIR)/Xregion/libXregion.la ++OS_LIB=$(LIB_DIR)/os/libos.la + COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB) + + noinst_LTLIBRARIES = libvnccommon.la +@@ -55,7 +56,7 @@ libvnc_la_CPPFLAGS = $(XVNC_CPPFLAGS) -I + + libvnc_la_LDFLAGS = -module -avoid-version -Wl,-z,now + +-libvnc_la_LIBADD = libvnccommon.la $(COMMON_LIBS) ++libvnc_la_LIBADD = libvnccommon.la $(COMMON_LIBS) $(OS_LIB) + + EXTRA_DIST = Xvnc.man + diff --git a/SOURCES/tigervnc11-ldnow.patch b/SOURCES/tigervnc11-ldnow.patch new file mode 100644 index 0000000..f6edd09 --- /dev/null +++ b/SOURCES/tigervnc11-ldnow.patch @@ -0,0 +1,12 @@ +diff -up tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am.ldnow tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am +--- tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am.ldnow 2011-10-31 09:14:40.000000000 +0100 ++++ tigervnc-1.2.0/unix/xserver/hw/vnc/Makefile.am 2012-08-22 15:51:47.013241342 +0200 +@@ -53,7 +53,7 @@ libvnc_la_CPPFLAGS = $(XVNC_CPPFLAGS) -I + -I$(top_srcdir)/include \ + ${XSERVERLIBS_CFLAGS} -I$(includedir) + +-libvnc_la_LDFLAGS = -module -avoid-version ++libvnc_la_LDFLAGS = -module -avoid-version -Wl,-z,now + + libvnc_la_LIBADD = libvnccommon.la $(COMMON_LIBS) + diff --git a/SOURCES/tigervnc11-rh692048.patch b/SOURCES/tigervnc11-rh692048.patch new file mode 100644 index 0000000..924c1cf --- /dev/null +++ b/SOURCES/tigervnc11-rh692048.patch @@ -0,0 +1,44 @@ +diff -up tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityClient.cxx.rh690245 tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityClient.cxx +--- tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityClient.cxx.rh690245 2011-02-21 14:14:16.000000000 +0100 ++++ tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityClient.cxx 2011-03-31 09:47:34.519099718 +0200 +@@ -45,7 +45,7 @@ StringParameter SecurityClient::secTypes + ("SecurityTypes", + "Specify which security scheme to use (None, VncAuth)", + #ifdef HAVE_GNUTLS +- "X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,VncAuth,None", ++ "VeNCrypt,X509Plain,TLSPlain,X509Vnc,TLSVnc,X509None,TLSNone,VncAuth,None", + #else + "VncAuth,None", + #endif +diff -up tigervnc-1.0.90-20110314svn4359/common/rfb/Security.cxx.rh690245 tigervnc-1.0.90-20110314svn4359/common/rfb/Security.cxx +--- tigervnc-1.0.90-20110314svn4359/common/rfb/Security.cxx.rh690245 2011-02-21 14:14:16.000000000 +0100 ++++ tigervnc-1.0.90-20110314svn4359/common/rfb/Security.cxx 2011-03-31 09:47:34.519099718 +0200 +@@ -67,7 +67,6 @@ const std::list Security::GetEn + list result; + list::iterator i; + +- result.push_back(secTypeVeNCrypt); + for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) + if (*i < 0x100) + result.push_back(*i); +@@ -105,8 +104,6 @@ bool Security::IsSupported(U32 secType) + for (i = enabledSecTypes.begin(); i != enabledSecTypes.end(); i++) + if (*i == secType) + return true; +- if (secType == secTypeVeNCrypt) +- return true; + + return false; + } +diff -up tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityServer.cxx.rh690245 tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityServer.cxx +--- tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityServer.cxx.rh690245 2011-02-21 14:50:17.000000000 +0100 ++++ tigervnc-1.0.90-20110314svn4359/common/rfb/SecurityServer.cxx 2011-03-31 10:06:43.595362302 +0200 +@@ -39,7 +39,7 @@ StringParameter SecurityServer::secTypes + ("SecurityTypes", + "Specify which security scheme to use (None, VncAuth)", + #ifdef HAVE_GNUTLS +- "VncAuth,TLSVnc", ++ "VncAuth", + #else + "VncAuth", + #endif diff --git a/SOURCES/tigervnc12-xorg113-glx.patch b/SOURCES/tigervnc12-xorg113-glx.patch new file mode 100644 index 0000000..c5a5621 --- /dev/null +++ b/SOURCES/tigervnc12-xorg113-glx.patch @@ -0,0 +1,36 @@ +diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/xvnc.cc.glx tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/xvnc.cc +--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/xvnc.cc.glx 2013-02-19 13:51:29.000000000 +0000 ++++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/xvnc.cc 2013-12-09 17:03:52.147179079 +0000 +@@ -1564,6 +1564,18 @@ static void vfbClientStateChange(Callbac + dispatchException &= ~DE_RESET; + } + ++#if XORG >= 113 ++#ifdef GLXEXT ++extern "C" void GlxExtensionInit(void); ++ ++static ExtensionModule glxExt = { ++ GlxExtensionInit, ++ "GLX", ++ &noGlxExtension ++}; ++#endif ++#endif ++ + void + InitOutput(ScreenInfo *screenInfo, int argc, char **argv) + { +@@ -1573,6 +1585,13 @@ InitOutput(ScreenInfo *screenInfo, int a + int i; + int NumFormats = 0; + ++#if XORG >= 113 ++#ifdef GLXEXT ++ if (serverGeneration == 1) ++ LoadExtension(&glxExt, TRUE); ++#endif ++#endif ++ + /* initialize pixmap formats */ + + /* must have a pixmap depth to match every screen depth */ diff --git a/SOURCES/vncserver.service b/SOURCES/vncserver.service new file mode 100644 index 0000000..4d55de2 --- /dev/null +++ b/SOURCES/vncserver.service @@ -0,0 +1,45 @@ +# The vncserver service unit file +# +# Quick HowTo: +# 1. Copy this file to /etc/systemd/system/vncserver@:.service +# 2. Edit and vncserver parameters appropriately +# ("runuser -l -c /usr/bin/vncserver %i -arg1 -arg2") +# 3. Run `systemctl daemon-reload` +# 4. Run `systemctl enable vncserver@:.service` +# +# DO NOT RUN THIS SERVICE if your local area network is +# untrusted! For a secure way of using VNC, you should +# limit connections to the local host and then tunnel from +# the machine you want to view VNC on (host A) to the machine +# whose VNC output you want to view (host B) +# +# [user@hostA ~]$ ssh -v -C -L 590N:localhost:590M hostB +# +# this will open a connection on port 590N of your hostA to hostB's port 590M +# (in fact, it ssh-connects to hostB and then connects to localhost (on hostB). +# See the ssh man page for details on port forwarding) +# +# You can then point a VNC client on hostA at vncdisplay N of localhost and with +# the help of ssh, you end up seeing what hostB makes available on port 590M +# +# Use "-nolisten tcp" to prevent X connections to your VNC server via TCP. +# +# Use "-localhost" to prevent remote VNC clients connecting except when +# doing so through a secure tunnel. See the "-via" option in the +# `man vncviewer' manual page. + + +[Unit] +Description=Remote desktop service (VNC) +After=syslog.target network.target + +[Service] +Type=forking +# Clean any existing files in /tmp/.X11-unix environment +ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :' +ExecStart=/sbin/runuser -l -c "/usr/bin/vncserver %i" +PIDFile=/home//.vnc/%H%i.pid +ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :' + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/vncserver.sysconfig b/SOURCES/vncserver.sysconfig new file mode 100644 index 0000000..4d0489b --- /dev/null +++ b/SOURCES/vncserver.sysconfig @@ -0,0 +1 @@ +# THIS FILE HAS BEEN REPLACED BY /lib/systemd/system/vncserver@.service diff --git a/SOURCES/vncviewer.desktop b/SOURCES/vncviewer.desktop new file mode 100644 index 0000000..fab46f0 --- /dev/null +++ b/SOURCES/vncviewer.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=TigerVNC Viewer +Name[fr]=Visionneur TigerVNC +Comment=Connect to VNC server and display remote desktop +Comment[fr]=Se connecter à un serveur VNC et afficher le bureau distant +Exec=/usr/bin/vncviewer +Icon=tigervnc +Terminal=false +Type=Application +StartupWMClass=TigerVNC Viewer: Connection Details +Categories=Network;RemoteAccess; diff --git a/SPECS/tigervnc.spec b/SPECS/tigervnc.spec new file mode 100644 index 0000000..f046a6f --- /dev/null +++ b/SPECS/tigervnc.spec @@ -0,0 +1,775 @@ +%global snap 20130314svn5065 + +Name: tigervnc +Version: 1.2.80 +Release: 0.31.%{snap}%{?dist} +Summary: A TigerVNC remote display system + +Group: User Interface/Desktops +License: GPLv2+ +URL: http://www.tigervnc.com + +Source0: %{name}-%{version}-%{snap}.tar.bz2 +Source1: vncserver.service +Source2: vncserver.sysconfig +Source3: 10-libvnc.conf +Source6: vncviewer.desktop +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: libX11-devel, automake, autoconf, libtool, gettext, gettext-autopoint +BuildRequires: libXext-devel, xorg-x11-server-source, libXi-devel +BuildRequires: xorg-x11-xtrans-devel, xorg-x11-util-macros, libXtst-devel +BuildRequires: libdrm-devel, libXt-devel, pixman-devel libXfont-devel +BuildRequires: libxkbfile-devel, openssl-devel, libpciaccess-devel +BuildRequires: mesa-libGL-devel, libXinerama-devel, ImageMagick +BuildRequires: freetype-devel, libXdmcp-devel +BuildRequires: desktop-file-utils, java-devel, jpackage-utils +BuildRequires: libjpeg-turbo-devel, gnutls-devel, pam-devel +BuildRequires: systemd, cmake, fltk-devel + +Requires(post): coreutils +Requires(postun):coreutils + +Requires: hicolor-icon-theme +Requires: tigervnc-license +Requires: tigervnc-icons + +Provides: vnc = 4.1.3-2, vnc-libs = 4.1.3-2 +Obsoletes: vnc < 4.1.3-2, vnc-libs < 4.1.3-2 +Provides: tightvnc = 1.5.0-0.15.20090204svn3586 +Obsoletes: tightvnc < 1.5.0-0.15.20090204svn3586 + +Patch4: tigervnc-cookie.patch +Patch10: tigervnc11-ldnow.patch +Patch11: tigervnc11-gethomedir.patch +Patch13: tigervnc11-rh692048.patch +Patch14: tigervnc12-xorg113-glx.patch +Patch15: tigervnc-inetd-nowait.patch +Patch16: tigervnc-setcursor-crash.patch +Patch17: tigervnc-manpages.patch +Patch18: tigervnc-shebang.patch +Patch19: tigervnc-1.3.0-xserver-1.15.patch +Patch20: tigervnc-zrle-crash.patch +Patch21: tigervnc-cursor.patch +Patch22: tigervnc-input.patch +Patch23: tigervnc-xstartup.patch +Patch24: tigervnc-CVE-2014-0011.patch + +%description +Virtual Network Computing (VNC) is a remote display system which +allows you to view a computing 'desktop' environment not only on the +machine where it is running, but from anywhere on the Internet and +from a wide variety of machine architectures. This package contains a +client which will allow you to connect to other desktops running a VNC +server. + +%package server +Summary: A TigerVNC server +Group: User Interface/X +Provides: vnc-server = 4.1.3-2, vnc-libs = 4.1.3-2 +Obsoletes: vnc-server < 4.1.3-2, vnc-libs < 4.1.3-2 +Provides: tightvnc-server = 1.5.0-0.15.20090204svn3586 +Obsoletes: tightvnc-server < 1.5.0-0.15.20090204svn3586 +Requires: perl +Requires: tigervnc-server-minimal +Requires: xorg-x11-xauth +Requires: xorg-x11-xinit +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Requires(post): systemd-sysv chkconfig + +%description server +The VNC system allows you to access the same desktop from a wide +variety of platforms. This package includes set of utilities +which make usage of TigerVNC server more user friendly. It also +contains x0vncserver program which can export your active +X session. + +%package server-minimal +Summary: A minimal installation of TigerVNC server +Group: User Interface/X +Requires(post): chkconfig +Requires(preun):chkconfig +Requires(preun):initscripts +Requires(postun):initscripts + +Requires: mesa-dri-drivers, xkeyboard-config, xorg-x11-xkb-utils +Requires: tigervnc-license + +%description server-minimal +The VNC system allows you to access the same desktop from a wide +variety of platforms. This package contains minimal installation +of TigerVNC server, allowing others to access the desktop on your +machine. + +%ifnarch s390 s390x +%package server-module +Summary: TigerVNC module to Xorg +Group: User Interface/X +Provides: vnc-server = 4.1.3-2, vnc-libs = 4.1.3-2 +Obsoletes: vnc-server < 4.1.3-2, vnc-libs < 4.1.3-2 +Provides: tightvnc-server-module = 1.5.0-0.15.20090204svn3586 +Obsoletes: tightvnc-server-module < 1.5.0-0.15.20090204svn3586 +Requires: xorg-x11-server-Xorg +Requires: tigervnc-license + +%description server-module +This package contains libvnc.so module to X server, allowing others +to access the desktop on your machine. +%endif + +%package server-applet +Summary: Java TigerVNC viewer applet for TigerVNC server +Group: User Interface/X +Requires: tigervnc-server, java, jpackage-utils +BuildArch: noarch + +%description server-applet +The Java TigerVNC viewer applet for web browsers. Install this package to allow +clients to use web browser when connect to the TigerVNC server. + +%package license +Summary: License of TigerVNC suite +Group: User Interface/X +BuildArch: noarch + +%description license +This package contains license of the TigerVNC suite + +%package icons +Summary: Icons for TigerVNC viewer +Group: User Interface/X +BuildArch: noarch + +%description icons +This package contains icons for TigerVNC viewer + +%prep +%setup -q -n %{name}-%{version}-%{snap} + +%patch4 -p1 -b .cookie +%patch10 -p1 -b .ldnow +%patch11 -p1 -b .gethomedir +%patch13 -p1 -b .rh692048 + +cp -r /usr/share/xorg-x11-server-source/* unix/xserver +pushd unix/xserver +for all in `find . -type f -perm -001`; do + chmod -x "$all" +done +patch -p1 -b --suffix .vnc < ../xserver114.patch +popd + +%patch14 -p1 -b .glx + +# Applied Debian patch to fix busy loop when run from inetd in nowait +# mode (bug #920373). +%patch15 -p1 -b .inetd-nowait + +%patch16 -p1 -b .setcursor-crash + +# Synchronise manpages and --help output (bug #980870). +%patch17 -p1 -b .manpages + +# Don't use shebang in vncserver script. +%patch18 -p1 -b .shebang + +# source compatibility with xserver 1.15 +%patch19 -p1 -b .115 + +# Avoid invalid read when ZRLE connection closed (upstream bug #133). +%patch20 -p1 -b .zrle-crash + +# Fixed viewer crash when cursor has not been set (bug #1051333). +%patch21 -p1 -b .cursor + +# Use keyboard input code from tigervnc-1.3.0 (bug #1053536). +%patch22 -p1 -b .input + +# Clearer xstartup file (bug #923655). +%patch23 -p1 -b .xstartup + +# Fixed heap-based buffer overflow (CVE-2014-0011, bug #1050928). +%patch24 -p1 -b .CVE-2014-0011 + +%build +%ifarch sparcv9 sparc64 s390 s390x +export CFLAGS="$RPM_OPT_FLAGS -fPIC" +%else +export CFLAGS="$RPM_OPT_FLAGS -fpic" +%endif +export CXXFLAGS="$CFLAGS" + +%{cmake} . +make %{?_smp_mflags} + +pushd unix/xserver +autoreconf -fiv +%configure \ + --disable-xorg --disable-xnest --disable-xvfb --disable-dmx \ + --disable-xwin --disable-xephyr --disable-kdrive --with-pic \ + --disable-static --disable-xinerama \ + --with-default-font-path="catalogue:%{_sysconfdir}/X11/fontpath.d,built-ins" \ + --with-fontdir=%{_datadir}/X11/fonts \ + --with-xkb-output=%{_localstatedir}/lib/xkb \ + --enable-install-libxf86config \ + --enable-glx --disable-dri --enable-dri2 \ + --disable-wayland \ + --disable-present \ + --disable-config-dbus \ + --disable-config-hal \ + --disable-config-udev \ + --with-dri-driver-path=%{_libdir}/dri \ + --without-dtrace \ + --disable-unit-tests \ + --disable-devel-docs \ + --disable-selective-werror + +make %{?_smp_mflags} +popd + +# Build icons +pushd media +make +popd + +# Build Java applet +pushd java +%{cmake} . +make +popd + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT + +pushd unix/xserver/hw/vnc +make install DESTDIR=$RPM_BUILD_ROOT +popd + +# Install systemd unit file +mkdir -p %{buildroot}%{_unitdir} +install -m644 %{SOURCE1} %{buildroot}%{_unitdir}/vncserver@.service +rm -rf %{buildroot}%{_initrddir} + +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig +install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers + +# Install desktop stuff +mkdir -p $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/{16x16,24x24,48x48}/apps + +pushd media/icons +for s in 16 24 48; do +install -m644 tigervnc_$s.png $RPM_BUILD_ROOT%{_datadir}/icons/hicolor/${s}x$s/apps/tigervnc.png +done +popd + +mkdir $RPM_BUILD_ROOT%{_datadir}/applications +desktop-file-install \ + --dir $RPM_BUILD_ROOT%{_datadir}/applications \ + %{SOURCE6} + +# Install Java applet +pushd java +mkdir -p $RPM_BUILD_ROOT%{_datadir}/vnc/classes +install -m755 VncViewer.jar $RPM_BUILD_ROOT%{_datadir}/vnc/classes +install -m644 com/tigervnc/vncviewer/index.vnc $RPM_BUILD_ROOT%{_datadir}/vnc/classes +popd + +%find_lang %{name} %{name}.lang + +# remove unwanted files +rm -f $RPM_BUILD_ROOT%{_libdir}/xorg/modules/extensions/libvnc.la + +%ifarch s390 s390x +rm -f $RPM_BUILD_ROOT%{_libdir}/xorg/modules/extensions/libvnc.so +%else +mkdir -p %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/ +install -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf +%endif + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +touch -c %{_datadir}/icons/hicolor +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor || : +fi + +%postun +touch -c %{_datadir}/icons/hicolor +if [ -x %{_bindir}/gtk-update-icon-cache ]; then + %{_bindir}/gtk-update-icon-cache -q %{_datadir}/icons/hicolor || : +fi + +%post server +%systemd_post vncserver.service + +%triggerun -- tigervnc-server < 1.0.90-6 +%{_bindir}/systemd-sysv-convert --save vncserver >/dev/null 2>&1 ||: +/sbin/chkconfig --del vncserver >/dev/null 2>&1 || : + +%preun server +%systemd_preun vncserver.service + +%postun server +%systemd_postun + +%files -f %{name}.lang +%defattr(-,root,root,-) +%doc README.txt +%{_bindir}/vncviewer +%{_datadir}/applications/* +%{_mandir}/man1/vncviewer.1* + +%files server +%defattr(-,root,root,-) +%config(noreplace) %{_sysconfdir}/sysconfig/vncservers +%{_unitdir}/vncserver@.service +%{_bindir}/x0vncserver +%{_bindir}/vncserver +%{_mandir}/man1/vncserver.1* +%{_mandir}/man1/x0vncserver.1* + +%files server-minimal +%defattr(-,root,root,-) +%{_bindir}/vncconfig +%{_bindir}/vncpasswd +%{_bindir}/Xvnc +%{_mandir}/man1/Xvnc.1* +%{_mandir}/man1/vncpasswd.1* +%{_mandir}/man1/vncconfig.1* + +%ifnarch s390 s390x +%files server-module +%defattr(-,root,root,-) +%{_libdir}/xorg/modules/extensions/libvnc.so +%config %{_sysconfdir}/X11/xorg.conf.d/10-libvnc.conf +%endif + +%files server-applet +%defattr(-,root,root,-) +%doc java/com/tigervnc/vncviewer/README +%{_datadir}/vnc/classes/* + +%files license +%doc LICENCE.TXT + +%files icons +%defattr(-,root,root,-) +%{_datadir}/icons/hicolor/*/apps/* + +%changelog +* Tue Sep 23 2014 Tim Waugh - 1.2.80-0.31.20130314svn5065 +- Rebuilt against xorg-x11-server to pick up ppc64le fix (bug #1140424). + +* Mon Mar 10 2014 Tim Waugh - 1.2.80-0.30.20130314svn5065 +- Fixed heap-based buffer overflow (CVE-2014-0011, bug #1050928). + +* Tue Feb 18 2014 Tim Waugh - 1.2.80-0.29.20130314svn5065 +- Previous patch was not applied. + +* Mon Feb 10 2014 Tim Waugh - 1.2.80-0.28.20130314svn5065 +- Clearer xstartup file (bug #923655). + +* Tue Jan 28 2014 Tim Waugh - 1.2.80-0.27.20130314svn5065 +- Use keyboard input code from tigervnc-1.3.0 (bug #1053536). + +* Fri Jan 24 2014 Daniel Mach - 1.2.80-0.26.20130314svn5065 +- Mass rebuild 2014-01-24 + +* Fri Jan 10 2014 Tim Waugh - 1.2.80-0.25.20130314svn5065 +- Fixed viewer crash when cursor has not been set (bug #1051333). + +* Fri Dec 27 2013 Daniel Mach - 1.2.80-0.24.20130314svn5065 +- Mass rebuild 2013-12-27 + +* Thu Dec 12 2013 Tim Waugh 1.2.80-0.23.20130314svn5065 +- Avoid invalid read when ZRLE connection closed (bug #1039926). + +* Tue Dec 10 2013 Tim Waugh 1.2.80-0.22.20130314svn5065 +- Fixed GLX initialisation (bug #1039126). + +* Tue Nov 19 2013 Tim Waugh 1.2.80-0.21.20130314svn5065 +- Better fix for PIDFile problem (bug #1031625). + +* Fri Nov 08 2013 Adam Jackson 1.2.80-0.20.20130314svn5065 +- Rebuild against xserver 1.15RC1 + +* Wed Jul 24 2013 Tim Waugh 1.2.80-0.18.20130314svn5065 +- Avoid PIDFile problems in systemd unit file (bug #983232). +- Don't use shebang in vncserver script. + +* Wed Jul 3 2013 Tim Waugh 1.2.80-0.18.20130314svn5065 +- Removed systemd_requires macro in order to fix the build. + +* Wed Jul 3 2013 Tim Waugh 1.2.80-0.17.20130314svn5065 +- Synchronise manpages and --help output (bug #980870). + +* Mon Jun 17 2013 Adam Jackson 1.2.80-0.16.20130314svn5065 +- tigervnc-setcursor-crash.patch: Attempt to paper over a crash in Xvnc when + setting the cursor. + +* Sat Jun 08 2013 Dennis Gilmore 1.2.80-0.15.20130314svn5065 +- bump to rebuild and pick up bugfix causing X to crash on ppc and arm + +* Thu May 23 2013 Tim Waugh 1.2.80-0.14.20130314svn5065 +- Use systemd rpm macros (bug #850340). Moved systemd requirements + from main package to server sub-package. +- Applied Debian patch to fix busy loop when run from inetd in nowait + mode (bug #920373). +- Added dependency on xorg-x11-xinit to server sub-package so that + default window manager can be found (bug #896284, bug #923655). +- Fixed bogus changelog date. + +* Thu Mar 14 2013 Adam Jackson 1.2.80-0.13.20130314svn5065 +- Less RHEL customization + +* Thu Mar 14 2013 Adam Tkac - 1.2.80-0.12.20130314svn5065 +- include /etc/X11/xorg.conf.d/10-libvnc.conf sample configuration (#712482) +- vncserver now honors specified -geometry parameter (#755947) + +* Tue Mar 12 2013 Adam Tkac - 1.2.80-0.11.20130307svn5060 +- update to r5060 +- split icons to separate package to avoid multilib issues + +* Tue Feb 19 2013 Adam Tkac - 1.2.80-0.10.20130219svn5047 +- update to r5047 (X.Org 1.14 support) + +* Fri Feb 15 2013 Fedora Release Engineering - 1.2.80-0.9.20121126svn5015 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Jan 21 2013 Adam Tkac - 1.2.80-0.8.20121126svn5015 +- rebuild due to "jpeg8-ABI" feature drop + +* Wed Jan 16 2013 Adam Tkac 1.2.80-0.7.20121126svn5015 +- rebuild + +* Tue Dec 04 2012 Adam Tkac 1.2.80-0.6.20121126svn5015 +- rebuild against new fltk + +* Mon Nov 26 2012 Adam Tkac 1.2.80-0.5.20121126svn5015 +- update to r5015 +- build with -fpic instead of -fPIC on all archs except s390/sparc + +* Wed Nov 7 2012 Peter Robinson 1.2.80-0.4.20120905svn4996 +- Build with -fPIC to fix FTBFS on ARM + +* Wed Oct 31 2012 Adam Jackson 1.2.80-0.3.20120905svn4996 +- tigervnc12-xorg113-glx.patch: Fix to only init glx on the first server + generation + +* Fri Sep 28 2012 Adam Jackson 1.2.80-0.2.20120905svn4996 +- tigervnc12-xorg113-glx.patch: Re-enable GLX against xserver 1.13 + +* Fri Aug 17 2012 Adam Tkac 1.2.80-0.1.20120905svn4996 +- update to 1.2.80 +- remove deprecated patches + - tigervnc-102434.patch + - tigervnc-viewer-reparent.patch + - tigervnc11-java7.patch +- patches merged + - tigervnc11-xorg111.patch + - tigervnc11-xorg112.patch + +* Fri Aug 10 2012 Dave Airlie 1.1.0-10 +- fix build against newer X server + +* Mon Jul 23 2012 Adam Jackson 1.1.0-9 +- Build with the Composite extension for feature parity with other X servers + +* Sat Jul 21 2012 Fedora Release Engineering - 1.1.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Jul 19 2012 Dave Airlie 1.1.0-7 +- fix building against X.org 1.13 + +* Wed Apr 04 2012 Adam Jackson 1.1.0-6 +- RHEL exclusion for -server-module on ppc* too + +* Mon Mar 26 2012 Adam Tkac - 1.1.0-5 +- clean Xvnc's /tmp environment in service file before startup +- fix building against the latest JAVA 7 and X.Org 1.12 + +* Sat Jan 14 2012 Fedora Release Engineering - 1.1.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Nov 22 2011 Adam Tkac - 1.1.0-3 +- don't build X.Org devel docs (#755782) +- applet: BR generic java-devel instead of java-gcj-devel (#755783) +- use runuser to start Xvnc in systemd service file (#754259) +- don't attepmt to restart Xvnc session during update/erase (#753216) + +* Fri Nov 11 2011 Adam Tkac - 1.1.0-2 +- libvnc.so: don't use unexported GetMaster function (#744881) +- remove nasm buildreq + +* Mon Sep 12 2011 Adam Tkac - 1.1.0-1 +- update to 1.1.0 +- update the xorg11 patch +- patches merged + - tigervnc11-glx.patch + - tigervnc11-CVE-2011-1775.patch + - 0001-Use-memmove-instead-of-memcpy-in-fbblt.c-when-memory.patch + +* Thu Jul 28 2011 Adam Tkac - 1.0.90-6 +- add systemd service file and remove legacy SysV initscript (#717227) + +* Thu May 12 2011 Adam Tkac - 1.0.90-5 +- make Xvnc buildable against X.Org 1.11 + +* Tue May 10 2011 Adam Tkac - 1.0.90-4 +- viewer can send password without proper validation of X.509 certs + (CVE-2011-1775) + +* Wed Apr 13 2011 Adam Tkac - 1.0.90-3 +- fix wrong usage of memcpy which caused screen artifacts (#652590) +- don't point to inaccessible link in sysconfig/vncservers (#644975) + +* Fri Apr 08 2011 Adam Tkac - 1.0.90-2 +- improve compatibility with vinagre client (#692048) + +* Tue Mar 22 2011 Adam Tkac - 1.0.90-1 +- update to 1.0.90 + +* Wed Feb 09 2011 Fedora Release Engineering - 1.0.90-0.32.20110117svn4237 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 17 2011 Adam Tkac 1.0.90-0.31.20110117svn4237 +- fix libvnc.so module loading + +* Mon Jan 17 2011 Adam Tkac 1.0.90-0.30.20110117svn4237 +- update to r4237 +- patches merged + - tigervnc11-optionsdialog.patch + - tigervnc11-rh607866.patch + +* Fri Jan 14 2011 Adam Tkac 1.0.90-0.29.20101208svn4225 +- improve patch for keyboard issues + +* Fri Jan 14 2011 Adam Tkac 1.0.90-0.28.20101208svn4225 +- attempt to fix various keyboard-related issues (key repeating etc) + +* Fri Jan 07 2011 Adam Tkac 1.0.90-0.27.20101208svn4225 +- render "Ok" and "Cancel" buttons in the options dialog correctly + +* Wed Dec 15 2010 Jan Görig 1.0.90-0.26.20101208svn4225 +- added vncserver lock file (#662784) + +* Fri Dec 10 2010 Adam Tkac 1.0.90-0.25.20101208svn4225 +- update to r4225 +- patches merged + - tigervnc11-rh611677.patch + - tigervnc11-rh633931.patch + - tigervnc11-xorg1.10.patch +- enable VeNCrypt and PAM support + +* Mon Dec 06 2010 Adam Tkac 1.0.90-0.24.20100813svn4123 +- rebuild against xserver 1.10.X +- 0001-Return-Success-from-generate_modkeymap-when-max_keys.patch merged + +* Wed Sep 29 2010 jkeating - 1.0.90-0.23.20100813svn4123 +- Rebuilt for gcc bug 634757 + +* Tue Sep 21 2010 Adam Tkac 1.0.90-0.22.20100420svn4030 +- drop xorg-x11-fonts-misc dependency (#636170) + +* Tue Sep 21 2010 Adam Tkac 1.0.90-0.21.20100420svn4030 +- improve patch for #633645 (fix tcsh incompatibilities) + +* Thu Sep 16 2010 Adam Tkac 1.0.90-0.20.20100813svn4123 +- press fake modifiers correctly (#633931) +- supress unneeded debug information emitted from initscript (#633645) + +* Wed Aug 25 2010 Adam Tkac 1.0.90-0.19.20100813svn4123 +- separate Xvnc, vncpasswd and vncconfig to -server-minimal subpkg (#626946) +- move license to separate subpkg and Requires it from main subpkgs +- Xvnc: handle situations when no modifiers exist well (#611677) + +* Fri Aug 13 2010 Adam Tkac 1.0.90-0.18.20100813svn4123 +- update to r4123 (#617973) +- add perl requires to -server subpkg (#619791) + +* Thu Jul 22 2010 Adam Tkac 1.0.90-0.17.20100721svn4113 +- update to r4113 +- patches merged + - tigervnc11-rh586406.patch + - tigervnc11-libvnc.patch + - tigervnc11-rh597172.patch + - tigervnc11-rh600070.patch + - tigervnc11-options.patch +- don't own %%{_datadir}/icons directory (#614301) +- minor improvements in the .desktop file (#616340) +- bundled libjpeg configure requires nasm; is executed even if system-wide + libjpeg is used + +* Fri Jul 02 2010 Adam Tkac 1.0.90-0.16.20100420svn4030 +- build against system-wide libjpeg-turbo (#494458) +- build no longer requires nasm + +* Mon Jun 28 2010 Adam Tkac 1.0.90-0.15.20100420svn4030 +- vncserver: accept <+optname> option when specified as the first one + +* Thu Jun 24 2010 Adam Tkac 1.0.90-0.14.20100420svn4030 +- fix memory leak in Xvnc input code (#597172) +- don't crash when receive negative encoding (#600070) +- explicitly disable udev configuration support +- add gettext-autopoint to BR + +* Mon Jun 14 2010 Adam Tkac 1.0.90-0.13.20100420svn4030 +- update URL about SSH tunneling in the sysconfig file (#601996) + +* Fri Jun 11 2010 Adam Tkac 1.0.90-0.12.20100420svn4030 +- use newer gettext +- autopoint now uses git instead of cvs, adjust BuildRequires appropriately + +* Thu May 13 2010 Adam Tkac 1.0.90-0.11.20100420svn4030 +- link libvnc.so "now" to catch "undefined symbol" errors during Xorg startup +- use always XkbConvertCase instead of XConvertCase (#580159, #586406) +- don't link libvnc.so against libXi.la, libdix.la and libxkb.la; use symbols + from Xorg instead + +* Thu May 13 2010 Adam Tkac 1.0.90-0.10.20100420svn4030 +- update to r4030 snapshot +- patches merged to upstream + - tigervnc11-rh522369.patch + - tigervnc11-rh551262.patch + - tigervnc11-r4002.patch + - tigervnc11-r4014.patch + +* Thu Apr 08 2010 Adam Tkac 1.0.90-0.9.20100219svn3993 +- add server-applet subpackage which contains Java vncviewer applet +- fix Java applet; it didn't work when run from web browser +- add xorg-x11-xkb-utils to server Requires + +* Fri Mar 12 2010 Adam Tkac 1.0.90-0.8.20100219svn3993 +- add French translation to vncviewer.desktop (thanks to Alain Portal) + +* Thu Mar 04 2010 Adam Tkac 1.0.90-0.7.20100219svn3993 +- don't crash during pixel format change (#522369, #551262) + +* Mon Mar 01 2010 Adam Tkac 1.0.90-0.6.20100219svn3993 +- add mesa-dri-drivers and xkeyboard-config to -server Requires +- update to r3993 1.0.90 snapshot + - tigervnc11-noexecstack.patch merged + - tigervnc11-xorg18.patch merged + - xserver18.patch is no longer needed + +* Wed Jan 27 2010 Jan Gorig 1.0.90-0.5.20091221svn3929 +- initscript LSB compliance fixes (#523974) + +* Fri Jan 22 2010 Adam Tkac 1.0.90-0.4.20091221svn3929 +- mark stack as non-executable in jpeg ASM code +- add xorg-x11-xauth to Requires +- add support for X.Org 1.8 +- drop shave sources, they are no longer needed + +* Thu Jan 21 2010 Adam Tkac 1.0.90-0.3.20091221svn3929 +- drop tigervnc-xorg25909.patch, it has been merged to X.Org upstream + +* Thu Jan 07 2010 Adam Tkac 1.0.90-0.2.20091221svn3929 +- add patch for upstream X.Org issue #25909 +- add libXdmcp-devel to build requires to build Xvnc with XDMCP support (#552322) + +* Mon Dec 21 2009 Adam Tkac 1.0.90-0.1.20091221svn3929 +- update to 1.0.90 snapshot +- patches merged + - tigervnc10-compat.patch + - tigervnc10-rh510185.patch + - tigervnc10-rh524340.patch + - tigervnc10-rh516274.patch + +* Mon Oct 26 2009 Adam Tkac 1.0.0-3 +- create Xvnc keyboard mapping before first keypress (#516274) + +* Thu Oct 08 2009 Adam Tkac 1.0.0-2 +- update underlying X source to 1.6.4-0.3.fc11 +- remove bogus '-nohttpd' parameter from /etc/sysconfig/vncservers (#525629) +- initscript LSB compliance fixes (#523974) +- improve -LowColorSwitch documentation and handling (#510185) +- honor dotWhenNoCursor option (and it's changes) every time (#524340) + +* Fri Aug 28 2009 Adam Tkac 1.0.0-1 +- update to 1.0.0 +- tigervnc10-rh495457.patch merged to upstream + +* Mon Aug 24 2009 Karsten Hopp 0.0.91-0.17 +- fix ifnarch s390x for server-module + +* Fri Aug 21 2009 Tomas Mraz - 0.0.91-0.16 +- rebuilt with new openssl + +* Tue Aug 04 2009 Adam Tkac 0.0.91-0.15 +- make Xvnc compilable + +* Sun Jul 26 2009 Fedora Release Engineering - 0.0.91-0.14.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Mon Jul 13 2009 Adam Tkac 0.0.91-0.13.1 +- don't write warning when initscript is called with condrestart param (#508367) + +* Tue Jun 23 2009 Adam Tkac 0.0.91-0.13 +- temporary use F11 Xserver base to make Xvnc compilable +- BuildRequires: libXi-devel +- don't ship tigervnc-server-module on s390/s390x + +* Mon Jun 22 2009 Adam Tkac 0.0.91-0.12 +- fix local rendering of cursor (#495457) + +* Thu Jun 18 2009 Adam Tkac 0.0.91-0.11 +- update to 0.0.91 (1.0.0 RC1) +- patches merged + - tigervnc10-rh499401.patch + - tigervnc10-rh497592.patch + - tigervnc10-rh501832.patch +- after discusion in upstream drop tigervnc-bounds.patch +- configure flags cleanup + +* Thu May 21 2009 Adam Tkac 0.0.90-0.10 +- rebuild against 1.6.1.901 X server (#497835) +- disable i18n, vncviewer is not UTF-8 compatible (#501832) + +* Mon May 18 2009 Adam Tkac 0.0.90-0.9 +- fix vncpasswd crash on long passwords (#499401) +- start session dbus daemon correctly (#497592) + +* Mon May 11 2009 Adam Tkac 0.0.90-0.8.1 +- remove merged tigervnc-manminor.patch + +* Tue May 05 2009 Adam Tkac 0.0.90-0.8 +- update to 0.0.90 + +* Thu Apr 30 2009 Adam Tkac 0.0.90-0.7.20090427svn3789 +- server package now requires xorg-x11-fonts-misc (#498184) + +* Mon Apr 27 2009 Adam Tkac 0.0.90-0.6.20090427svn3789 +- update to r3789 + - tigervnc-rh494801.patch merged +- tigervnc-newfbsize.patch is no longer needed +- fix problems when vncviewer and Xvnc run on different endianess (#496653) +- UltraVNC and TightVNC clients work fine again (#496786) + +* Wed Apr 08 2009 Adam Tkac 0.0.90-0.5.20090403svn3751 +- workaround broken fontpath handling in vncserver script (#494801) + +* Fri Apr 03 2009 Adam Tkac 0.0.90-0.4.20090403svn3751 +- update to r3751 +- patches merged + - tigervnc-xclients.patch + - tigervnc-clipboard.patch + - tigervnc-rh212985.patch +- basic RandR support in Xvnc (resize of the desktop) +- use built-in libjpeg (SSE2/MMX accelerated encoding on x86 platform) +- use Tight encoding by default +- use TigerVNC icons + +* Tue Mar 03 2009 Adam Tkac 0.0.90-0.3.20090303svn3631 +- update to r3631 + +* Tue Mar 03 2009 Adam Tkac 0.0.90-0.2.20090302svn3621 +- package review related fixes + +* Mon Mar 02 2009 Adam Tkac 0.0.90-0.1.20090302svn3621 +- initial package, r3621