From 365a22c63cb292ea494f39ebc48a37e322e5eb14 Mon Sep 17 00:00:00 2001 From: runge Date: Tue, 21 Dec 2010 12:04:02 -0500 Subject: [PATCH] x11vnc: touchscreen uinput support and Java viewer mousewheel support. See x11vnc/ChangeLog for rest. --- classes/ssl/SignedUltraViewerSSL.jar | Bin 112724 -> 113117 bytes classes/ssl/SignedVncViewer.jar | Bin 88791 -> 89208 bytes classes/ssl/UltraViewerSSL.jar | Bin 109640 -> 110040 bytes classes/ssl/VncViewer.jar | Bin 85809 -> 86228 bytes classes/ssl/ss_vncviewer | 12 + ...iewer-cursor-colors+no-tab-traversal.patch | 62 +- ...ghtvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 169 +- .../ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 123 +- prepare_x11vnc_dist.sh | 4 +- x11vnc/8to24.c | 8 +- x11vnc/ChangeLog | 16 + x11vnc/Makefile.am | 2 +- x11vnc/README | 549 ++++-- x11vnc/RELEASE-NOTES | 1553 +++++++++++++++++ x11vnc/appshare.c | 8 +- x11vnc/cleanup.c | 3 + x11vnc/gui.c | 8 +- x11vnc/help.c | 186 +- x11vnc/keyboard.c | 24 +- x11vnc/keyboard.h | 2 +- x11vnc/linuxfb.c | 1 + x11vnc/macosx.c | 1 + x11vnc/macosxCG.c | 4 + x11vnc/misc/Makefile.am | 2 +- x11vnc/misc/README | 4 + x11vnc/misc/qt_tslib_inject.pl | 1064 +++++++++++ x11vnc/misc/uinput.pl | 946 ++++++++++ x11vnc/pointer.c | 10 +- x11vnc/remote.c | 42 +- x11vnc/scan.c | 12 +- x11vnc/screen.c | 24 +- x11vnc/sslhelper.c | 15 +- x11vnc/ssltools.h | 53 +- x11vnc/uinput.c | 401 ++++- x11vnc/uinput.h | 1 + x11vnc/unixpw.c | 10 +- x11vnc/user.c | 1 + x11vnc/util.h | 4 +- x11vnc/v4l.c | 18 +- x11vnc/x11vnc.1 | 193 +- x11vnc/x11vnc.c | 38 +- x11vnc/x11vnc.h | 2 + x11vnc/x11vnc_defs.c | 2 +- x11vnc/xevents.c | 1 + x11vnc/xevents.h | 1 + x11vnc/xrecord.c | 6 +- x11vnc/xrecord.h | 2 +- x11vnc/xwrappers.c | 44 +- 48 files changed, 5200 insertions(+), 431 deletions(-) create mode 100644 x11vnc/RELEASE-NOTES create mode 100755 x11vnc/misc/qt_tslib_inject.pl create mode 100755 x11vnc/misc/uinput.pl diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar index eccb9b9f09d7b882a60ca0887bfa05a884f993d5..6c187370444ada76d894d6e52311df96ff8566eb 100644 GIT binary patch delta 32047 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 JdNU2`{{e-p>Kp(7 delta 31668 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 MgHitWw$32_55U*tQUCw| diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar index f0d8bfa44ee3e338b7089940025edf386a0871ff..95c0b0bec7de8c1575160e976ccc456d9c320b40 100644 GIT binary patch delta 25376 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

D8_99{1ju;~x10Yq#us7}>P#k@5to7eYCu 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 BAV2^B delta 28855 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

9!2XY4KoGa-`y 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 NO#vDxg8t*;{{UFD9-jaJ diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar index 46d59d0f707c35dd0241414804adc78f83472ce6..9453c6fd2959174be6c55b464d228ed6a835efe3 100644 GIT binary patch delta 22499 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 delta 22080 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 0) { ++ ptrmask = 16; ++ } else if (clicks < 0) { ++ ptrmask = 8; ++ } else { ++ return; ++ } ++ ++ eventBuf[eventBufLen++] = (byte) PointerEvent; ++ eventBuf[eventBufLen++] = (byte) ptrmask; ++ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); ++ eventBuf[eventBufLen++] = (byte) (x & 0xff); ++ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); ++ eventBuf[eventBufLen++] = (byte) (y & 0xff); ++ ++ os.write(eventBuf, 0, eventBufLen); ++ } ++ + // + // Write a pointer event message. We may need to send modifier key events + // around it to set the correct modifier state. +@@ -992,6 +1038,19 @@ boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); int key; @@ -99,7 +138,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto if (evt.isActionKey()) { // -@@ -1025,6 +1052,13 @@ +@@ -1025,6 +1084,13 @@ return; } @@ -113,7 +152,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto } else { // -@@ -1036,6 +1070,7 @@ +@@ -1036,6 +1102,7 @@ key = keyChar; @@ -121,7 +160,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto if (key < 0x20) { if (evt.isControlDown()) { key += 0x60; -@@ -1121,6 +1156,16 @@ +@@ -1121,6 +1188,16 @@ int oldModifiers = 0; void writeModifierKeyEvents(int newModifiers) { @@ -138,7 +177,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); -diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java +diff -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java --- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 +++ vnc_javasrc/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 @@ -0,0 +1,2067 @@ @@ -2209,7 +2248,119 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + private Base64Coder() {} + +} -diff -x VncCanvas.java -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java +diff -Naur vnc_javasrc.orig/VncCanvas.java vnc_javasrc/VncCanvas.java +--- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 ++++ vnc_javasrc/VncCanvas.java 2010-11-30 21:01:15.000000000 -0500 +@@ -28,13 +28,14 @@ + import java.lang.*; + import java.util.zip.*; + ++import java.util.Collections; + + // + // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. + // + + class VncCanvas extends Canvas +- implements KeyListener, MouseListener, MouseMotionListener { ++ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { + + VncViewer viewer; + RfbProto rfb; +@@ -81,6 +82,20 @@ + cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); + cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); + ++ // kludge to not show any Java cursor in the canvas since we are ++ // showing the soft cursor (should be a user setting...) ++ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( ++ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), ++ "dot"); ++ this.setCursor(dot); ++ ++ // while we are at it... get rid of the keyboard traversals that ++ // make it so we can't type a Tab character: ++ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, ++ Collections.EMPTY_SET); ++ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, ++ Collections.EMPTY_SET); ++ + colors = new Color[256]; + for (int i = 0; i < 256; i++) + colors[i] = new Color(cm8.getRGB(i)); +@@ -169,6 +184,7 @@ + inputEnabled = true; + addMouseListener(this); + addMouseMotionListener(this); ++ addMouseWheelListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(true); + } +@@ -177,6 +193,7 @@ + inputEnabled = false; + removeMouseListener(this); + removeMouseMotionListener(this); ++ removeMouseWheelListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(false); + } +@@ -1190,6 +1207,9 @@ + public void mouseDragged(MouseEvent evt) { + processLocalMouseEvent(evt, true); + } ++ public void mouseWheelMoved(MouseWheelEvent evt) { ++ processLocalMouseWheelEvent(evt); ++ } + + public void processLocalKeyEvent(KeyEvent evt) { + if (viewer.rfb != null && rfb.inNormalProtocol) { +@@ -1221,6 +1241,19 @@ + evt.consume(); + } + ++ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { ++ if (viewer.rfb != null && rfb.inNormalProtocol) { ++ synchronized(rfb) { ++ try { ++ rfb.writeWheelEvent(evt); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } ++ rfb.notify(); ++ } ++ } ++ } ++ + public void processLocalMouseEvent(MouseEvent evt, boolean moved) { + if (viewer.rfb != null && rfb.inNormalProtocol) { + if (moved) { +@@ -1387,9 +1420,9 @@ + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 | +- (pixBuf[i * 4 + 1] & 0xFF) << 16 | +- (pixBuf[i * 4 + 2] & 0xFF) << 8 | +- (pixBuf[i * 4 + 3] & 0xFF); ++ (pixBuf[i * 4 + 2] & 0xFF) << 16 | ++ (pixBuf[i * 4 + 1] & 0xFF) << 8 | ++ (pixBuf[i * 4 + 0] & 0xFF); + } + } else { + result = 0; // Transparent pixel +@@ -1403,9 +1436,9 @@ + result = cm8.getRGB(pixBuf[i]); + } else { + result = 0xFF000000 | +- (pixBuf[i * 4 + 1] & 0xFF) << 16 | +- (pixBuf[i * 4 + 2] & 0xFF) << 8 | +- (pixBuf[i * 4 + 3] & 0xFF); ++ (pixBuf[i * 4 + 2] & 0xFF) << 16 | ++ (pixBuf[i * 4 + 1] & 0xFF) << 8 | ++ (pixBuf[i * 4 + 0] & 0xFF); + } + } else { + result = 0; // Transparent pixel +diff -Naur vnc_javasrc.orig/VncViewer.java vnc_javasrc/VncViewer.java --- vnc_javasrc.orig/VncViewer.java 2004-03-04 08:34:25.000000000 -0500 +++ vnc_javasrc/VncViewer.java 2010-03-27 17:57:04.000000000 -0400 @@ -29,6 +29,7 @@ diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch index 224d825..3309860 100644 --- a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch +++ b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch @@ -1685,7 +1685,7 @@ diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java choices[shareDesktopIndex].select("Yes"); diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java --- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400 -+++ JavaViewer/RfbProto.java 2010-03-27 17:59:56.000000000 -0400 ++++ JavaViewer/RfbProto.java 2010-11-30 22:13:58.000000000 -0500 @@ -31,6 +31,7 @@ import java.net.Socket; import java.util.*; @@ -2662,7 +2662,45 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java os.write(b); // } -@@ -1610,6 +1971,21 @@ +@@ -1506,6 +1867,37 @@ + final static int META_MASK = InputEvent.META_MASK; + final static int ALT_MASK = InputEvent.ALT_MASK; + ++ void writeWheelEvent(MouseWheelEvent evt) throws IOException { ++ eventBufLen = 0; ++ ++ int x = evt.getX(); ++ int y = evt.getY(); ++ ++ if (x < 0) x = 0; ++ if (y < 0) y = 0; ++ ++ int ptrmask; ++ ++ int clicks = evt.getWheelRotation(); ++ System.out.println("writeWheelEvent: clicks: " + clicks); ++ if (clicks > 0) { ++ ptrmask = 16; ++ } else if (clicks < 0) { ++ ptrmask = 8; ++ } else { ++ return; ++ } ++ ++ eventBuf[eventBufLen++] = (byte) PointerEvent; ++ eventBuf[eventBufLen++] = (byte) ptrmask; ++ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); ++ eventBuf[eventBufLen++] = (byte) (x & 0xff); ++ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); ++ eventBuf[eventBufLen++] = (byte) (y & 0xff); ++ ++ os.write(eventBuf, 0, eventBufLen); ++ } ++ + // + // Write a pointer event message. We may need to send modifier key events + // around it to set the correct modifier state. +@@ -1610,6 +2002,21 @@ boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); @@ -2684,7 +2722,7 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java int key; if (evt.isActionKey()) { -@@ -1685,6 +2061,9 @@ +@@ -1685,6 +2092,9 @@ default : return; } @@ -2694,7 +2732,7 @@ diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java } else { -@@ -1794,6 +2173,16 @@ +@@ -1794,6 +2204,16 @@ int oldModifiers = 0; void writeModifierKeyEvents(int newModifiers) { @@ -4784,18 +4822,31 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java +} diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java --- JavaViewer.orig/VncCanvas.java 2005-11-21 18:50:18.000000000 -0500 -+++ JavaViewer/VncCanvas.java 2007-05-31 15:33:20.000000000 -0400 -@@ -27,6 +27,9 @@ ++++ JavaViewer/VncCanvas.java 2010-11-30 22:57:50.000000000 -0500 +@@ -27,6 +27,13 @@ import java.lang.*; import java.util.zip.*; +// begin runge/x11vnc +import java.util.Collections; ++// end runge/x11vnc ++ ++// begin runge/x11vnc ++// all the MouseWheel stuff below. +// end runge/x11vnc // // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. -@@ -85,6 +88,22 @@ +@@ -34,7 +41,7 @@ + + class VncCanvas + extends Canvas +- implements KeyListener, MouseListener, MouseMotionListener { ++ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { + + VncViewer viewer; + RfbProto rfb; +@@ -85,6 +92,22 @@ cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); @@ -4818,7 +4869,23 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java colors = new Color[256]; // sf@2005 - Now Default for (int i = 0; i < 256; i++) -@@ -202,6 +221,9 @@ +@@ -186,6 +209,7 @@ + inputEnabled = true; + addMouseListener(this); + addMouseMotionListener(this); ++ addMouseWheelListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(true); + } +@@ -193,6 +217,7 @@ + inputEnabled = false; + removeMouseListener(this); + removeMouseMotionListener(this); ++ removeMouseWheelListener(this); + if (viewer.showControls) { + viewer.buttonPanel.enableRemoteAccessControls(false); + } +@@ -202,6 +227,9 @@ public void setPixelFormat() throws IOException { // sf@2005 - Adding more color modes @@ -4828,7 +4895,7 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java if (viewer.options.eightBitColors > 0) { viewer.options.oldEightBitColors = viewer.options.eightBitColors; -@@ -237,6 +259,9 @@ +@@ -237,6 +265,9 @@ } else { @@ -4838,7 +4905,7 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java rfb.writeSetPixelFormat( 32, 24, -@@ -376,12 +401,14 @@ +@@ -376,12 +407,14 @@ // Start/stop session recording if necessary. viewer.checkRecordingStatus(); @@ -4859,7 +4926,7 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java // // main dispatch loop -@@ -390,6 +417,9 @@ +@@ -390,6 +423,9 @@ while (true) { // Read message type from the server. int msgType = rfb.readServerMessageType(); @@ -4869,7 +4936,37 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java // Process the message depending on its type. switch (msgType) { -@@ -1532,9 +1562,14 @@ +@@ -1332,6 +1368,9 @@ + public void mouseDragged(MouseEvent evt) { + processLocalMouseEvent(evt, true); + } ++ public void mouseWheelMoved(MouseWheelEvent evt) { ++ processLocalMouseWheelEvent(evt); ++ } + + public void processLocalKeyEvent(KeyEvent evt) { + if (viewer.rfb != null && rfb.inNormalProtocol) { +@@ -1367,6 +1406,19 @@ + evt.consume(); + } + ++ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { ++ if (viewer.rfb != null && rfb.inNormalProtocol) { ++ synchronized(rfb) { ++ try { ++ rfb.writeWheelEvent(evt); ++ } catch (Exception e) { ++ e.printStackTrace(); ++ } ++ rfb.notify(); ++ } ++ } ++ } ++ + public void processLocalMouseEvent(MouseEvent evt, boolean moved) { + if (viewer.rfb != null && rfb.inNormalProtocol) { + if (moved) { +@@ -1532,9 +1584,14 @@ else { result = @@ -4887,7 +4984,7 @@ diff -Naur JavaViewer.orig/VncCanvas.java JavaViewer/VncCanvas.java } } else { result = 0; // Transparent pixel -@@ -1565,9 +1600,14 @@ +@@ -1565,9 +1622,14 @@ else { result = diff --git a/prepare_x11vnc_dist.sh b/prepare_x11vnc_dist.sh index 2f6fec1..d72100d 100644 --- a/prepare_x11vnc_dist.sh +++ b/prepare_x11vnc_dist.sh @@ -19,7 +19,7 @@ sed -e "s/LibVNCServer, [^,)]*\([(,]\)*/x11vnc, $VERSION\1/g" \ mv Makefile.am Makefile.am.LibVNCServer -echo "EXTRA_DIST=tightvnc-1.3dev5-vncviewer-alpha-cursor.patch README.LibVNCServer" > Makefile.am +echo "EXTRA_DIST=tightvnc-1.3dev5-vncviewer-alpha-cursor.patch RELEASE-NOTES README.LibVNCServer" > Makefile.am echo "" >> Makefile.am echo "if HAVE_SYSTEM_LIBVNCSERVER" >> Makefile.am echo "SUBDIRS=x11vnc classes" >> Makefile.am @@ -41,6 +41,7 @@ sed -e "s/^SUBDIRS.*$/#SUBDIRS=libvncserver libvncclient x11vnc classes/" \ mv README README.LibVNCServer cp x11vnc/README ./README +cp x11vnc/RELEASE-NOTES ./RELEASE-NOTES cat LibVNCServer.spec.in | \ sed -e "s/Johannes.Schindelin@gmx.de/runge@karlrunge.com/gi" \ @@ -134,4 +135,5 @@ make x11vnc-${VERSION}.tar.gz for f in configure.ac Makefile.am x11vnc/Makefile.am libvncserver/Makefile.am libvncclient/Makefile.am classes/Makefile.am classes/ssl/Makefile.am acinclude.m4 README; do mv -f $f.LibVNCServer $f done +rm -f ./RELEASE-NOTES diff --git a/x11vnc/8to24.c b/x11vnc/8to24.c index 75ab68a..30c3da2 100644 --- a/x11vnc/8to24.c +++ b/x11vnc/8to24.c @@ -720,7 +720,7 @@ static int check_depth_win(Window win, Window top, XWindowAttributes *attr) { if (store_it) { int i, j = -1, none = -1, nomap = -1; - int new = 0; + int newc = 0; if (attr->map_state == IsViewable) { /* count the visible ones: */ multivis_count++; @@ -754,7 +754,7 @@ if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr->depth); } else if (none >= 0) { /* put it in the first None slot */ j = none; - new = 1; + newc = 1; } else if (nomap >=0) { /* put it in the first unmapped slot */ j = nomap; @@ -791,8 +791,8 @@ if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", wi windows_8bpp[j].x = x; windows_8bpp[j].y = y; - if (new || now_vis) { -if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis); + if (newc || now_vis) { +if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, newc, now_vis); /* mark it immediately if a new one: */ X_UNLOCK; /* dont forget the giant lock */ mark_rect_as_modified(x, y, x + attr->width, diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 8eb44c7..7ed6f78 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,19 @@ +2010-12-21 Karl Runge + * x11vnc: Add RELEASE-NOTES. Call shutdown_uinput() when exiting. + Free some minor memory. Do not use GetMainDevice() on macosx. + Add utility scripts qt_tslib_inject.pl and uinput.pl. Option + -ungrabboth (not useful.) X11VNC_SB_FACTOR -sb user tweak. + X11VNC_REFLECT_{bitsPerSample,samplesPerPixel,bytesPerPixel} + for -reflect vncclient. Fix minor fd leaks. For -create mode + preserve LC_ALL; FIND_DISPLAY_NO_VT_FIND, FIND_DISPLAY_NO_LSOF, + and X11VNC_CREATE_LC_ALL_C_OK. Speed up -find and -create scripts + for large installations. Enable direct event input modes to + bypass uinput. TSLIB support for uinput touchscreens. Handle + pressure events on touchscreens. User can set X11VNC_UINPUT_BUS + and X11VNC_UINPUT_VERSION. Allow Tab switch in -create login: + prompt. Fix bug in setting bpp for -rawfb. Java viewers now + handle mousewheel events. No vars named new. + 2010-09-10 Karl Runge * x11vnc: update classes/ssl jars, patches, and script. update prepare_x11vnc_dist.sh to 0.9.13. Makefile.am no top_srcdir diff --git a/x11vnc/Makefile.am b/x11vnc/Makefile.am index 163f930..32f0978 100644 --- a/x11vnc/Makefile.am +++ b/x11vnc/Makefile.am @@ -16,7 +16,7 @@ desktopdir = $(datadir)/applications desktop_DATA = x11vnc.desktop man_MANS=x11vnc.1 -EXTRA_DIST=ChangeLog README tkx11vnc $(man_MANS) $(desktop_DATA) +EXTRA_DIST=ChangeLog README RELEASE-NOTES tkx11vnc $(man_MANS) $(desktop_DATA) if CYGIPC LD_CYGIPC=-lcygipc diff --git a/x11vnc/README b/x11vnc/README index 8666aad..310ec36 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -2,7 +2,7 @@ Copyright (C) 2002-2010 Karl J. Runge All rights reserved. -x11vnc README file Date: Fri Sep 10 12:29:36 EDT 2010 +x11vnc README file Date: Tue Dec 21 11:45:35 EST 2010 The following information is taken from these URLs: @@ -241,7 +241,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick * Have x11vnc (0.9.3 or later) available to run on the remote host (i.e. in $PATH.) * Download and unpack a SSVNC bundle (1.0.19 or later, e.g. - ssvnc_no_windows-1.0.23.tar.gz) on the Viewer-side machine. + ssvnc_no_windows-1.0.28.tar.gz) on the Viewer-side machine. * Start the SSVNC Terminal Services mode GUI: ./ssvnc/bin/tsvnc * Enter your remote username@hostname (e.g. fred@far-away.east) in the "VNC Terminal Server" entry. @@ -909,10 +909,43 @@ make Here are some features that will appear in the 0.9.13 release: - * Coming Soon! - - - Here are some features that appeared in the 0.9.12 release: + * Improved support for non-X11 touchscreen devices (e.g. handheld or + cell phone) via Linux uinput input injection. Additional tuning + parameters are added. TSLIB touchscreen calibration is supported. + Tested on Qtmoko Neo Freerunner. A tool, misc/uinput.pl, is + provided to diagnose uinput behavior on new devices. The env. + vars. X11VNC_UINPUT_BUS and X11VNC_UINPUT_VERSION are available if + leaving them unset does not work. + * The Linux uinput non-X11 input injection can now be bypassed: + events can be directly written to the /dev/input/event devices + specified by the user (direct_abs=..., etc.) A -pipeinput input + injection helper script, misc/qt_tslib_inject.pl is provided as a + tweakable non-builtin direct input injection method. + * The list of new uinput parameters for the above two features is: + pressure, tslib_cal, touch_always, dragskip, btn_touch; + direct_rel, direct_abs, direct_btn, direct_key. + * The included SSL enabled Java VNC Viewers now handle Mouse Wheel + events. + * miscellaneous new features and changes: In -reflect mode, the + libvncclient connection can now have the pixel format modified via + the environment variables X11VNC_REFLECT_bitsPerSample, + X11VNC_REFLECT_samplesPerPixel, and X11VNC_REFLECT_bytesPerPixel + * In -create mode the following environment variables are added to + fine tune the behavior: FIND_DISPLAY_NO_LSOF: do not use lsof(1) + to try to determine the Linux VT, FIND_DISPLAY_NO_VT_FIND: do not + try to determine the Linux VT at all, X11VNC_CREATE_LC_ALL_C_OK: + do not bother undoing the setting LC_ALL=C that the create_display + script sets. The performance of the -create script has been + improved for large installations (100's of user sessions on one + machine.) + * In -unixpw mode, one can now Tab from login: to Password. + * An environment variable, X11VNC_SB_FACTOR, allows one to scale the + -sb screenblank sleep time from the default 2 secs. + * Documented that -grabkbd is no longer working with some/most + window managers (it can prevent resizing and menu posting.) + + + Here are some features that appeared in the 0.9.12 release (Sep/2010): * One can now specify the maximum number of displays that can be created in -create mode via the env. var. X11VNC_CREATE_MAX_DISPLAYS @@ -922,7 +955,7 @@ make killed by the display manager. * A compile time bug is fixed so that configuring using --with-system-libvncserver pointing to LibVNCServer 0.9.7 works - again. A bug from forced used of Xdefs.h is worked around. + again. A bug from forced use of Xdefs.h is worked around. Here are some features that appeared in the 0.9.11 release (Aug/2010): @@ -2028,56 +2061,63 @@ http://www.karlrunge.com/x11vnc/faq.html: Q-114: Can I export via VNC a Webcam or TV tuner framebuffer using x11vnc? - Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application - running on my handheld or PC using the Linux console framebuffer (i.e. - not X11)? + Q-115: Can I connect via VNC to a Qt-embedded/Qt-enhanced/Qtopia + application running on my handheld, cell phone, or PC using the Linux + console framebuffer (i.e. not X11)? - Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + Q-116: How do I inject touch screen input into an + Qt-embedded/Qt-enhanced/Qtopia cell phone such as openmoko/qtmoko Neo + Freerunner? + + Q-117: Now that non-X11 devices can be exported via VNC using x11vnc, can I build it with no dependencies on X11 header files and libraries? - Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + Q-118: How do I cross compile x11vnc for a different architecture than + my Linux i386 or amd64 PC? + + Q-119: Does x11vnc support Mac OS X Aqua/Quartz displays natively (i.e. no X11 involved)? - Q-118: Can x11vnc be used as a VNC reflector/repeater to improve + Q-120: Can x11vnc be used as a VNC reflector/repeater to improve performance for the case of a large number of simultaneous VNC viewers (e.g. classroom broadcasting or a large demo)? - Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Q-121: Can x11vnc be used during a Linux, Solaris, etc. system Installation so the Installation can be done remotely? [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, Thanks, etc.] - Q-120: Does the Clipboard/Selection get transferred between the + Q-122: Does the Clipboard/Selection get transferred between the vncviewer and the X display? - Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + Q-123: Can I use x11vnc to record a Shock Wave Flash (or other format) video of my desktop, e.g. to record a tutorial or demo? - Q-122: Can I transfer files back and forth with x11vnc? + Q-124: Can I transfer files back and forth with x11vnc? - Q-123: Which UltraVNC extensions are supported? + Q-125: Which UltraVNC extensions are supported? - Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Q-126: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for Unix? I.e. something very simple for a naive user to initiate a reverse vnc connection from their Unix desktop to a helpdesk operator's VNC Viewer. - Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + Q-127: Can I (temporarily) mount my local (viewer-side) Windows/Samba File share on the machine where x11vnc is running? - Q-126: Can I redirect CUPS print jobs from the remote desktop where + Q-128: Can I redirect CUPS print jobs from the remote desktop where x11vnc is running to a printer on my local (viewer-side) machine? - Q-127: How can I hear the sound (audio) from the remote applications + Q-129: How can I hear the sound (audio) from the remote applications on the desktop I am viewing via x11vnc? - Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + Q-130: Why don't I hear the "Beeps" in my X session (e.g. when typing tput bel in an xterm)? - Q-129: Does x11vnc work with IPv6? + Q-131: Does x11vnc work with IPv6? - Q-130: Thanks for your program or for your help! Can I make a + Q-132: Thanks for your program or for your help! Can I make a donation? _________________________________________________________________ @@ -7884,9 +7924,9 @@ minal #2) x11vnc.) - Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application - running on my handheld or PC using the Linux console framebuffer (i.e. - not X11)? + Q-115: Can I connect via VNC to a Qt-embedded/Qt-enhanced/Qtopia + application running on my handheld, cell phone, or PC using the Linux + console framebuffer (i.e. not X11)? Yes, the basic method for this is the -rawfb scheme where the Linux console framebuffer (usually /dev/fb0) is polled and the uinput driver @@ -7945,10 +7985,50 @@ minal #2) Update: We are finding some setups like Qtopia on the IPAQ do not allow mouse input via uinput. Please help us debug this problem by trying x11vnc on your device and letting us know what does and does - not work. - - - Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + not work. See the next FAQ for a possible workaround for touchscreens. + + + Q-116: How do I inject touch screen input into an + Qt-embedded/Qt-enhanced/Qtopia cell phone such as openmoko/qtmoko Neo + Freerunner? + + The qtmoko project does not use X11 for the graphical display. + Unfortunately the Linux uinput method described in the previous FAQ + does not work because Qt is using TSLIB (touch screen library) to + process the input and it only reads from one device (often + /dev/input/event1) and not from the new UINPUT device that x11vnc + creates (under -pipeinput UINPUT) + + So something else needs to be done. It was discovered that by simply + writing the touchscreen events directly to /dev/input/event1 then + input can be injected into the system. There is no x11vnc builtin mode + for this yet (until we understand it better), but there is a working + script provided in x11vnc/misc/qt_tslib_inject.pl. So one could use it + this way for example: + x11vnc ... -rawfb console -pipeinput path/to/qt_tslib_inject.pl -env INJECT_O +PTIONS=clickonly,cal=/etc/pointercal + + Read the script for how to enable other options and what the above + options mean (e.g. /etc/pointercal contains TSLIB's calibration + parameters and are necessary to achieve accurate pointing.) + + The x11vnc/misc/qt_tslib_inject.pl script can potentially be modified + to handle other devices where the uinput method fails. It could also + be modified to create 'hot keys', etc. + + Please let us know how things go if you try this out; there is much to + learn about synthetic input injection in handhelds and cell phones. As + we learn more we can develop a builtin x11vnc mode for this sort of + injection. + + Update Dec/2010: There is experimental built-in UINPUT support in the + x11vnc development tarball for qtmoko with touchpad managed by tslib. + See -pipeinput UINPUT for more info. Here is an example: + x11vnc -rawfb console -pipeinput UINPUT:touch,tslib_cal=/etc/pointercal,dire +ct_abs=/dev/input/event1,nouinput,dragskip=3 + + + Q-117: Now that non-X11 devices can be exported via VNC using x11vnc, can I build it with no dependencies on X11 header files and libraries? Yes, as of Jul/2006 x11vnc enables building for -rawfb only support. @@ -7962,7 +8042,40 @@ minal #2) know what you did. - Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + Q-118: How do I cross compile x11vnc for a different architecture than + my Linux i386 or amd64 PC? + + You will need a cross-compiling toolchain. Perhaps your distro + provides these or you can find a HOWTO for your distro. We found a + nice one at qtmoko.org for building armel binaries on Debian Linux + i386 machines. It includes most of the libraries that x11vnc needs. We + use that example here. + + We ran this script to set PATH, configure, and build: +#!/bin/sh + +# toolchain from: qtmoko-debian-toolchain-armv4t-eabi.tar.gz + +export PATH=/opt/toolchains/arm920t-eabi/bin:$PATH + +env CC=arm-linux-gcc ./configure --host=arm-linux --without-avahi + +make + +arm-linux-strip ./x11vnc/x11vnc +ls -l ./x11vnc/x11vnc + + Note we had to include --without-avahi due to lack of + libavahi-client.so.3 supplied by the toolchain we used. One would need + to add it if it was desired on the target machine. We also stripped + the binary to make it smaller. + + For an embedded system one may also want to add --without-x if the + embedded system does not use X11 and the -rawfb mechanism must be + used. + + + Q-119: Does x11vnc support Mac OS X Aqua/Quartz displays natively (i.e. no X11 involved)? Yes, since Nov/2006 in the development tree (x11vnc-0.8.4 tarball) @@ -8086,7 +8199,7 @@ ONLY do that for Mac OS X 10.5.x and NOT for 10.6.x (which doesn't need it anyway). - Q-118: Can x11vnc be used as a VNC reflector/repeater to improve + Q-120: Can x11vnc be used as a VNC reflector/repeater to improve performance for the case of a large number of simultaneous VNC viewers (e.g. classroom broadcasting or a large demo)? @@ -8195,7 +8308,7 @@ need it anyway). us know what you did. A really nice thing would be some sort of auto-discovery of your repeater, etc... - Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Q-121: Can x11vnc be used during a Linux, Solaris, etc. system Installation so the Installation can be done remotely? This can be done, but it doesn't always work because it depends on how @@ -8288,7 +8401,7 @@ need it anyway). [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, Thanks, etc.] - Q-120: Does the Clipboard/Selection get transferred between the + Q-122: Does the Clipboard/Selection get transferred between the vncviewer and the X display? As of Jan/2004 x11vnc supports the "CutText" part of the RFB (aka VNC) @@ -8342,7 +8455,7 @@ need it anyway). cutbuffers. - Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + Q-123: Can I use x11vnc to record a Shock Wave Flash (or other format) video of my desktop, e.g. to record a tutorial or demo? Yes, it is possible with a number of tools that record VNC and @@ -8354,7 +8467,7 @@ need it anyway). parameters should be applied to x11vnc to speed up its polling for this sort of application, e.g. "-wait 10 -defer 10". - Q-122: Can I transfer files back and forth with x11vnc? + Q-124: Can I transfer files back and forth with x11vnc? As of Oct/2005 and May/2006 x11vnc enables, respectively, the TightVNC and UltraVNC file transfer implementations that were added to @@ -8402,7 +8515,7 @@ need it anyway). control you will probably be foiled by the "-rfbversion 3.6" issue. - Q-123: Which UltraVNC extensions are supported? + Q-125: Which UltraVNC extensions are supported? Some of them are supported. To get UltraVNC Viewers to attempt to use these extensions you will need to supply this option to x11vnc: @@ -8432,7 +8545,7 @@ need it anyway). ultravnc_repeater.pl - Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Q-126: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for Unix? I.e. something very simple for a naive user to initiate a reverse vnc connection from their Unix desktop to a helpdesk operator's VNC Viewer. @@ -8670,7 +8783,7 @@ connect = localhost:5501 You will find the details here. - Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + Q-127: Can I (temporarily) mount my local (viewer-side) Windows/Samba File share on the machine where x11vnc is running? You will have to use an external network redirection for this. @@ -8720,7 +8833,7 @@ d,ip=127.0.0.1,port=1139 Sep 2006 it is there for testing.) - Q-126: Can I redirect CUPS print jobs from the remote desktop where + Q-128: Can I redirect CUPS print jobs from the remote desktop where x11vnc is running to a printer on my local (viewer-side) machine? You will have to use an external network redirection for this. @@ -8812,7 +8925,7 @@ d,ip=127.0.0.1,port=1139 Sep 2006 it is there for testing.) - Q-127: How can I hear the sound (audio) from the remote applications + Q-129: How can I hear the sound (audio) from the remote applications on the desktop I am viewing via x11vnc? You will have to use an external network audio mechanism for this. @@ -8913,7 +9026,7 @@ or: provide (as of Sep/2006 it is there for testing.) - Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + Q-130: Why don't I hear the "Beeps" in my X session (e.g. when typing tput bel in an xterm)? As of Dec/2003 "Beep" XBell events are tracked by default. The X @@ -8926,7 +9039,7 @@ or: redirector such as esd. - Q-129: Does x11vnc work with IPv6? + Q-131: Does x11vnc work with IPv6? Update: as of Apr/2010 in the 0.9.10 x11vnc development tarball, there is now built-in support for IPv6 (128 bit internet addresses.) See the @@ -9025,7 +9138,7 @@ or: Contributions: - Q-130: Thanks for your program or for your help! Can I make a + Q-132: Thanks for your program or for your help! Can I make a donation? Please do (any amount is appreciated; very few have donated) and thank @@ -12172,7 +12285,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-09-10 +x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-20 x11vnc options: -display disp -auth file -N @@ -12193,83 +12306,83 @@ x11vnc options: -vncconnect -novncconnect -allow host1[,host2..] -localhost -listen6 str -nolookup -input string -grabkbd -grabptr - -grabalways -viewpasswd string -passwdfile filename - -showrfbauth filename -unixpw [list] -unixpw_nis [list] - -unixpw_cmd cmd -find -finddpy - -listdpy -findauth [disp] -create - -xdummy -xvnc -xvnc_redirect - -xdummy_xvfb -create_xsrv str -svc - -svc_xdummy -svc_xvnc -svc_xdummy_xvfb - -xdmsvc -sshxdmsvc -unixpw_system_greeter - -redirect port -display WAIT:... -vencrypt mode - -anontls mode -sslonly -dhparams file - -nossl -ssl [pem] -ssltimeout n - -sslnofail -ssldir dir -sslverify path - -sslCRL path -sslGenCA [dir] -sslGenCert type name - -sslEncKey pem -sslCertInfo pem -sslDelCert pem - -sslScripts -stunnel [pem] -stunnel3 [pem] - -enc cipher:keyfile -https [port] -httpsredir [port] - -http_oneport -ssh user@host:disp -usepw - -storepasswd pass file -nopw -accept string - -afteraccept string -gone string -users list - -noshm -flipbyteorder -onetile - -solid [color] -blackout string -xinerama - -noxinerama -xtrap -xrandr [mode] - -rotate string -padgeom WxH -o logfile - -flag file -rmflag file -rc filename - -norc -env VAR=VALUE -prog /path/to/x11vnc - -h, -help -?, -opts -V, -version - -license -dbg -q, -quiet - -v, -verbose -bg -modtweak - -nomodtweak -xkb -noxkb - -capslock -skip_lockkeys -noskip_lockkeys - -skip_keycodes string -sloppy_keys -skip_dups - -noskip_dups -add_keysyms -noadd_keysyms - -clear_mods -clear_keys -clear_all - -remap string -norepeat -repeat - -nofb -nobell -nosel - -noprimary -nosetprimary -noclipboard - -nosetclipboard -seldir string -cursor [mode] - -nocursor -cursor_drag -arrow n - -noxfixes -alphacut n -alphafrac fraction - -alpharemove -noalphablend -nocursorshape - -cursorpos -nocursorpos -xwarppointer - -noxwarppointer -always_inject -buttonmap string - -nodragging -ncache n -ncache_cr - -ncache_no_moveraise -ncache_no_dtchange -ncache_no_rootpixmap - -ncache_keep_anims -ncache_old_wm -ncache_pad n - -debug_ncache -wireframe [str] -nowireframe - -nowireframelocal -wirecopyrect mode -nowirecopyrect - -debug_wireframe -scrollcopyrect mode -noscrollcopyrect - -scr_area n -scr_skip list -scr_inc list - -scr_keys list -scr_term list -scr_keyrepeat lo-hi - -scr_parms string -fixscreen string -debug_scroll - -noxrecord -grab_buster -nograb_buster - -debug_grabs -debug_sel -pointer_mode n - -input_skip n -allinput -input_eagerly - -speeds rd,bw,lat -wmdt string -debug_pointer - -debug_keyboard -defer time -wait time - -extra_fbur n -wait_ui factor -setdefer n - -nowait_bog -slow_fb time -xrefresh time - -nap -nonap -sb time - -readtimeout n -ping n -nofbpm - -fbpm -nodpms -dpms - -forcedpms -clientdpms -noserverdpms - -noultraext -chatwindow -noxdamage - -xd_area A -xd_mem f -sigpipe string - -threads -nothreads -fs f - -gaps n -grow n -fuzz n - -debug_tiles -snapfb -rawfb string - -freqtab file -pipeinput cmd -macnodim - -macnosleep -macnosaver -macnowait - -macwheel n -macnoswap -macnoresize - -maciconanim n -macmenu -macuskbd - -gui [gui-opts] -remote command -query variable - -QD variable -sync -query_retries str - -remote_prefix str -noremote -yesremote - -unsafe -safer -privremote - -nocmds -allowedcmds list -deny_all - + -ungrabboth -grabalways -viewpasswd string + -passwdfile filename -showrfbauth filename -unixpw [list] + -unixpw_nis [list] -unixpw_cmd cmd -find + -finddpy -listdpy -findauth [disp] + -create -xdummy -xvnc + -xvnc_redirect -xdummy_xvfb -create_xsrv str + -svc -svc_xdummy -svc_xvnc + -svc_xdummy_xvfb -xdmsvc -sshxdmsvc + -unixpw_system_greeter -redirect port -display WAIT:... + -vencrypt mode -anontls mode -sslonly + -dhparams file -nossl -ssl [pem] + -ssltimeout n -sslnofail -ssldir dir + -sslverify path -sslCRL path -sslGenCA [dir] + -sslGenCert type name -sslEncKey pem -sslCertInfo pem + -sslDelCert pem -sslScripts -stunnel [pem] + -stunnel3 [pem] -enc cipher:keyfile -https [port] + -httpsredir [port] -http_oneport -ssh user@host:disp + -usepw -storepasswd pass file -nopw + -accept string -afteraccept string -gone string + -users list -noshm -flipbyteorder + -onetile -solid [color] -blackout string + -xinerama -noxinerama -xtrap + -xrandr [mode] -rotate string -padgeom WxH + -o logfile -flag file -rmflag file + -rc filename -norc -env VAR=VALUE + -prog /path/to/x11vnc -h, -help -?, -opts + -V, -version -license -dbg + -q, -quiet -v, -verbose -bg + -modtweak -nomodtweak -xkb + -noxkb -capslock -skip_lockkeys + -noskip_lockkeys -skip_keycodes string -sloppy_keys + -skip_dups -noskip_dups -add_keysyms + -noadd_keysyms -clear_mods -clear_keys + -clear_all -remap string -norepeat + -repeat -nofb -nobell + -nosel -noprimary -nosetprimary + -noclipboard -nosetclipboard -seldir string + -cursor [mode] -nocursor -cursor_drag + -arrow n -noxfixes -alphacut n + -alphafrac fraction -alpharemove -noalphablend + -nocursorshape -cursorpos -nocursorpos + -xwarppointer -noxwarppointer -always_inject + -buttonmap string -nodragging -ncache n + -ncache_cr -ncache_no_moveraise -ncache_no_dtchange + -ncache_no_rootpixmap -ncache_keep_anims -ncache_old_wm + -ncache_pad n -debug_ncache -wireframe [str] + -nowireframe -nowireframelocal -wirecopyrect mode + -nowirecopyrect -debug_wireframe -scrollcopyrect mode + -noscrollcopyrect -scr_area n -scr_skip list + -scr_inc list -scr_keys list -scr_term list + -scr_keyrepeat lo-hi -scr_parms string -fixscreen string + -debug_scroll -noxrecord -grab_buster + -nograb_buster -debug_grabs -debug_sel + -pointer_mode n -input_skip n -allinput + -input_eagerly -speeds rd,bw,lat -wmdt string + -debug_pointer -debug_keyboard -defer time + -wait time -extra_fbur n -wait_ui factor + -setdefer n -nowait_bog -slow_fb time + -xrefresh time -nap -nonap + -sb time -readtimeout n -ping n + -nofbpm -fbpm -nodpms + -dpms -forcedpms -clientdpms + -noserverdpms -noultraext -chatwindow + -noxdamage -xd_area A -xd_mem f + -sigpipe string -threads -nothreads + -fs f -gaps n -grow n + -fuzz n -debug_tiles -snapfb + -rawfb string -freqtab file -pipeinput cmd + -macnodim -macnosleep -macnosaver + -macnowait -macwheel n -macnoswap + -macnoresize -maciconanim n -macmenu + -macuskbd -gui [gui-opts] -remote command + -query variable -QD variable -sync + -query_retries str -remote_prefix str -noremote + -yesremote -unsafe -safer + -privremote -nocmds -allowedcmds list + -deny_all LibVNCServer options: -rfbport port TCP port for RFB protocol @@ -12303,7 +12416,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-09-10 +x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-20 (type "x11vnc -opts" to just list the options.) @@ -13085,6 +13198,12 @@ Options: Some degree of cooperation from the person at the display is assumed. This is intended for remote help-desk or educational usage modes. + + Note: on some recent (12/2010) X servers and/or + desktops, -grabkbd no longer works: it prevents the + window manager from resizing windows and similar things. + Try -ungrabboth below (might not work.) + -grabptr As -grabkbd, but for the mouse pointer using XGrabPointer(3X11). Unfortunately due to the way the X server works, the mouse can still be moved around by the @@ -13094,6 +13213,11 @@ Options: act on the local user's input. Again, some degree of cooperation from the person at the display is assumed. +-ungrabboth Whenever there is any input (either keyboard or + pointer), ungrab *both* the keyboard and the pointer + while injecting the synthetic input. This is to allow + window managers, etc. a chance to grab. + -grabalways Apply both -grabkbd and -grabptr even when no VNC viewers are connected. If you only want one of them, use the -R remote control to turn the other back on, @@ -13639,6 +13763,15 @@ Options: xauth extract - $DISPLAY" + NOTE: As specified in the previous paragraph, you can + supply your own WAIT:cmd=... program or script, BUT + there are two very useful *BUILT-IN* ones: FINDDISPLAY + (alias -find above) and FINDCREATEDISPLAY (alias -create + above.) Most people use these instead of creating + their own script. Read the following (especially the + BUILT-IN modes sections) to see how to configure these + two useful builtin -display WAIT: modes. + In the case of -unixpw (and -unixpw_nis only if x11vnc is running as root), then the cmd= command is run as the user who just authenticated via the login and @@ -13670,6 +13803,11 @@ Options: your long "login:" line press the Up arrow once (before typing anything else). + Most of these colon options only apply to the builtin + FINDDISPLAY and FINDCREATEDISPLAY modes, but note + that they are passed to the extrenal command in the + environment as well and so could be used. + In the login panel, press F1 to get a list of the available options that you can add after the username. @@ -13703,23 +13841,19 @@ Options: and the user put "geom=1600x1200" in his ~/.x11vnc_create file. - To troubleshoot the FINDCREATEDISPLAY mechanism, - set the following env. var. to an output log file, - e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt - To disable the option setting set the environment variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc. To set any other options, the user can use the gui (x11vnc -gui connect) or the remote control method (x11vnc -R opt:val) during his VNC session. - The combination of -display WAIT:cmd=... and -unixpw - allows automatic pairing of an unix authenticated VNC - user with his desktop. This could be very useful on - SunRays and also any system where multiple users share - a given machine. The user does not need to remember - special ports or passwords set up for his desktop - and VNC. + So we see the combination of -display WAIT:cmd=... and + -unixpw allows automatic pairing of an unix + authenticated VNC user with his desktop. This could + be very useful on SunRays and also any system where + multiple users share a given machine. The user does + not need to remember special ports or passwords set up + for his desktop and VNC. A nice way to use WAIT:cmd=... is out of inetd(8) (it automatically forks a new x11vnc for each user). @@ -13731,13 +13865,15 @@ Options: process that will not switch, but it is only encoding and decoding the encrypted stream at that point. - Automatic Finding of User X Sessions: + BUILT-IN modes: + + -- Automatic Finding of User X Sessions -- As a special case, WAIT:cmd=FINDDISPLAY will run a script that works on most Unixes to determine a user's DISPLAY variable and xauthority data (see who(1)). - The option "-find" is an alias for this mode. + NOTE: The option "-find" is an alias for this mode. To have this default script printed to stdout (e.g. for customization) run with WAIT:cmd=FINDDISPLAY-print To @@ -13781,7 +13917,12 @@ Options: X11VNC_SKIP_DISPLAY=all then all display finding fails as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) - Automatic Creation of User X Sessions: + On some systems lsof(1) can be very slow. Set the + env. var. FIND_DISPLAY_NO_LSOF=1 to skip using lsof to + try to find the Linux VT the X server is running on. + set FIND_DISPLAY_NO_VT_FIND=1 to avoid looking at all. + + -- Automatic Creation of User X Sessions -- An interesting option is WAIT:cmd=FINDCREATEDISPLAY that is like FINDDISPLAY in that is uses the same method @@ -13790,13 +13931,19 @@ Options: for the user. This is the only time x11vnc tries to actually start up an X server. - The option "-create" is an alias for this mode. + NOTE: The option "-create" is an alias for this mode. It will start looking for an open display number at :20 Override via X11VNC_CREATE_STARTING_DISPLAY_NUMBER=n By default 80 X displays are allowed (i.e. going to :99) Override via X11VNC_CREATE_MAX_DISPLAYS=n + For its heuristics, the create display script sets + LC_ALL=C so that command output is uniform. By default + it will try to restore LC_ALL right before starting the + user session. However, if you don't mind it keeping + LC_ALL=C set the env. var.: X11VNC_CREATE_LC_ALL_C_OK=1 + By default FINDCREATEDISPLAY will try Xvfb and then Xdummy: @@ -13823,6 +13970,10 @@ Options: it to terminate (or kill the X server process if all else fails). + To troubleshoot the FINDCREATEDISPLAY mechanism, + set the following env. var. to an output log file, + e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt + So this is a somewhat odd mode for x11vnc in that it will start up and poll virtual X servers! This can be used from, say, inetd(8) to provide a means of @@ -16302,6 +16453,7 @@ t -sb time Time in seconds after NO activity (e.g. screen blank) to really throttle down the screen polls (i.e. sleep for about 1.5 secs). Use 0 to disable. Default: 60 + Set the env. var. X11VNC_SB_FACTOR to scale it. -readtimeout n Set LibVNCServer rfbMaxClientWait to n seconds. On slow links that take a long time to paint the first @@ -16749,18 +16901,19 @@ er using the 'console_guess' string printed at startup, be sure to indicate the snap: method. - uinput: If the Linux version appears to be 2.6 or - later and the "uinput" module appears to be present - (modprobe uinput), then the uinput method will be used - instead of /dev/ttyN. uinput allows insertion of BOTH - keystrokes and mouse input and so it preferred when - accessing graphical (e.g. QT-embedded) linux console - apps. See -pipeinput UINPUT below for more information - on this mode; you will have to use -pipeinput if you - want to tweak any UINPUT parameters. You may also want - to also use the -nodragging and -cursor none options. - Use "console0", etc or -pipeinput CONSOLE to force - the /dev/ttyN method. + uinput: If the Linux version appears to be 2.6 + or later and the "uinput" module appears to be + present (modprobe uinput), then the uinput method + will be used instead of /dev/ttyN. uinput allows + insertion of BOTH keystrokes and mouse input and so it + preferred when accessing graphical (e.g. QT-embedded) + linux console apps. It also provides more accurate + keystroke insertion. See -pipeinput UINPUT below for + more information on this mode; you will have to use + -pipeinput if you want to tweak any UINPUT parameters. + You may also want to also use the -nodragging and + -cursor none options. Use "console0", etc or + -pipeinput CONSOLE to force the /dev/ttyN method. Note you can change the Linux VT remotely using the chvt(1) command to make the one you want be the active @@ -16800,7 +16953,11 @@ er to improve performance in the case of many (e.g. > 10) simultaneous VNC viewers, and you try a divide and conquer scheme to reduce bandwidth and improve - responsiveness. + responsiveness. (However, another user found this mode + useful to export a demo display through a slow link: + then multiple demo viewers connected to the reflecting + x11vnc on the fast side of the link, and so avoided + all of the demo viewers going through the slow link.) For example, if there will be 64 simultaneous VNC viewers this can lead to a lot of redundant VNC traffic @@ -16831,6 +16988,13 @@ er to "file:path_to_file" to indicate a file containing the password as its first line. + To set the pixel format that x11vnc requests as a VNC + CLIENT set the env. vars: X11VNC_REFLECT_bitsPerSample + X11VNC_REFLECT_samplesPerPixel, and + X11VNC_REFLECT_bytesPerPixel; the defaults are 8, 3, 4. + 2, 3, 1 would give a low color mode. See the function + rfbGetClient() in libvncclient for more info. + The VNC HOST mode implies -shared. Use -noshared as a subsequent cmdline option to disable sharing. @@ -16893,7 +17057,8 @@ er The UINPUT mode currently only does US keyboards (a scan code option may be added), and not all keysyms - are supported. + are supported. But it is probably more accurate than + the "CONSOLE" method. You may want to use the options -cursor none and -nodragging in this mode. @@ -16933,16 +17098,6 @@ er cause jerkiness or unexpected behavior with menus, etc. Use reset=0 to disable. - If the uinput device has an absolute pointer (as opposed - to a normal mouse that is a relative pointer) you can - specify the option "abs". Note that a touchpad - on a laptop is an absolute device to some degree. - This (usually) avoids all the problems with mouse - acceleration. If x11vnc has trouble deducing the size - of the device, use "abs=WxH". Furthermore, if the - device is a touchscreen (assumed to have an absolute - pointer) use "touch" or "touch=WxH". - If you set the env. var X11VNC_UINPUT_THRESHOLDS then the thresh=n mode will be enabled. It is currently not working well. If |dx| <= thresh and |dy| < thresh @@ -16952,8 +17107,70 @@ er Example: -pipeinput UINPUT:accel=4.0 -cursor none - You can also set the env. var X11VNC_UINPUT_DEBUG=1 or - higher to get debugging output for UINPUT mode. + If the uinput device has an absolute pointer (as opposed + to a normal mouse that is a relative pointer) you can + specify the option "abs". Note that a touchpad + on a laptop is an absolute device to some degree. + This (usually) avoids all the problems with mouse + acceleration. If x11vnc has trouble deducing the + size of the device, use "abs=WxH". Furthermore, + if the device is a touchscreen (assumed to have an + absolute pointer) use "touch" or "touch=WxH". + For touchscreens, when a mouse button is pressed, + a pressure increase is injected, and when the button + is released a pressure of zero is injected. + + If touch has been set, use "touch_always=1" to + indicate whenever the mouse moves with no button + pressed, a touch event of zero pressure should be + sent anyway. Also use "btn_touch=1" to indicate a + BTN_TOUCH keystroke press or release should be sent + instead of a pressure change. Set "dragskip=n" to + skip n dragged mouse touches (with pressure applied) + before injecting one. To indicate the pressure that + should be sent when there is a button click for a + touchscreen device, specify pressure=n, e.g. n=5. The + default is n=1. + + If a touch screen is being used ("touch" above) + and it is having its input processed by tslib, you can + specify the tslib calibration file via tslib_cal=. + For example, tslib_cal=/etc/pointercal. To get accurate + or even usable positioning this is required when tslib + is in use. + + The Linux uinput mechanism can be bypassed and one can + write input events DIRECTLY to the devices instead. + To do this, specify one or more of the following + for the input classes: direct_rel= + direct_abs= direct_btn= or + direct_key=. The file is usually + something like /dev/input/event1 but you can specify + any device file or pipe. You must specify each one + of the above classes even if they correspond to the + same device file (rel/abs and btn are often the same.) + Look at the file /proc/bus/input/devices to get an idea + what is available and the device filenames. Note: + The /dev/input/mouse* devices do not seem to work, + use the corresponding /dev/input/event* file instead. + Any input class not directly specified as above will be + handled via the uinput mechanism. To disable creating a + uinput device (and thereby discarding unhandled input), + specify "nouinput". + + Examples: + + -pipeinput UINPUT:direct_abs=/dev/input/event1 + + this was used on a qtmoko Neo freerunner (armel): + + -pipeinput UINPUT:touch,tslib_cal=/etc/pointercal, + direct_abs=/dev/input/event1,nouinput,dragskip=4 + + (where the long line has been split into two.) + + You can set the env. var X11VNC_UINPUT_DEBUG=1 or higher + to get debugging output for UINPUT mode. -macnodim For the native MacOSX server, disable dimming. -macnosleep For the native MacOSX server, disable display sleep. diff --git a/x11vnc/RELEASE-NOTES b/x11vnc/RELEASE-NOTES new file mode 100644 index 0000000..0d5c4b9 --- /dev/null +++ b/x11vnc/RELEASE-NOTES @@ -0,0 +1,1553 @@ + +x11vnc 0.9.13 2010-12-20 + +New in the 0.9.13 x11vnc release: + + Improved support for non-X11 touchscreen devices (e.g. handheld or + cell phone) via Linux uinput input injection. Additional + tuning parameters are added. TSLIB touchscreen calibration + is supported. Tested on Qtmoko Neo Freerunner. + + A tool, misc/uinput.pl, is provided to diagnose uinput + behavior on new devices. + + The env. vars. X11VNC_UINPUT_BUS and X11VNC_UINPUT_VERSION + are available if leaving them unset does not work. + + The Linux uinput non-X11 input injection can now be bypassed: + events can be directly written to the /dev/input/event + devices specified by the user (direct_abs=..., etc.) + + A -pipeinput input injection helper script, + misc/qt_tslib_inject.pl is provided as a tweakable + non-builtin direct input injection method. + + The list of new uinput parameters for the above two features is: + pressure, tslib_cal, touch_always, dragskip, btn_touch; + direct_rel, direct_abs, direct_btn, direct_key. + + The included SSL enabled Java VNC Viewers now handle Mouse + Wheel events. + + + miscellaneous new features and changes: + + In -reflect mode, the libvncclient connection can now have + the pixel format modified via the environment + variables X11VNC_REFLECT_bitsPerSample, + X11VNC_REFLECT_samplesPerPixel, and + X11VNC_REFLECT_bytesPerPixel + + In -create mode the following environment variables are added + to fine tune the behavior: FIND_DISPLAY_NO_LSOF: + do not use lsof(1) to try to determine the Linux VT, + FIND_DISPLAY_NO_VT_FIND: do not try to determine the + Linux VT at all, X11VNC_CREATE_LC_ALL_C_OK: do not bother + undoing the setting LC_ALL=C that the create_display + script sets. The performance of the -create script + has been improved for large installations (100's of + user sessions on one machine.) + + In -unixpw mode, one can now Tab from login: to Password. + + An environment variable, X11VNC_SB_FACTOR, allows one to scale + the -sb screenblank sleep time from the default 2 secs. + + In -rawfb mode, a bug is fixed in setting the number of bits + per pixel. + + Documented that -grabkbd is no longer working with some/most + window managers (it can prevent resizing and menu posting.) + + The macosx deprecated interface GetMainDevice() call is removed. + Compile with -DX11VNC_MACOSX_USE_GETMAINDEVICE if needed + for an old macosx version... + + Miscellaneous code cleanup. + +----------------------------------------------------------------------------- + + +x11vnc 0.9.12 2010-09-10 + +New in the 0.9.12 x11vnc release: + + One can now specify the maximum number of displays + that can be created in -create mode via the + env. var. X11VNC_CREATE_MAX_DISPLAYS + + The X11VNC_NO_LIMIT_SHM env. var. is added to skip any + automatic shared memory reduction. + + The kdm display manager is now detected when trying not to get + killed by the display manager. + + miscellaneous new features and changes: + + A compile error is fixed when using --with-system-libvncserver + pointing to LibVNCServer 0.9.7. + + -nevershared -forever usage mode is documented. + + Old SuSE broken thread local storage is documented. + + x11vnc exit cases are documented. + + A compile bug from forced use of Xdefs.h is worked around. + + +----------------------------------------------------------------------------- + + +x11vnc 0.9.11 2010-08-08 + +New in the 0.9.11 x11vnc release: + + The source tree is synchronized with the most recent libvncclient + (this only affects -reflect mode.) The build is fixed + for incompatibilities when using an external LibVNCServer + (e.g. ./configure --with-system-libvncserver...) + + The SSL enabled Java VNC Viewer Makefile has been modified so + that the jar files that are built are compatible back + to Java 1.4. + + In -reflect mode cursor position updates are now handled + correctly. + + In -create/-unixpw mode, the env. var. FD_USERPREFS may be set + to a filename in the user's home directory that includes + default username:options values (so the options do not + need to be typed every time at the login prompt.) + + miscellaneous new features and changes: + + An option -always_inject is provided: Even if there is no + displacement (dx = dy = 0) for a VNC mouse event force + the pointer to the indicated x,y position anyway. + + New java viewer debugging and workaround applet parameters: + debugKeyboard mapF5_to_atsign forbid_Ctrl_Alt + + You can set X11VNC_AVAHI_NAME, X11VNC_AVAHI_HOST, and/or + X11VNC_AVAHI_PORT environment variables to override the + default values. For example: -env X11VNC_AVAHI_NAME=wally + + When opening the X11 display extra XAUTHLOCALHOSTNAME settings + are attempted. + + +----------------------------------------------------------------------------- + + +x11vnc 0.9.10 2010-05-03 + +New in the 0.9.10 x11vnc release: + + IPv6 is now supported for all usage modes: forward and reverse + connections, SSL and unencrypted, etc. + + The included SSL enabled Java VNC viewer applet now supports + Chained SSL Certificates (x11vnc -ssl always has.) + The applet autodects x11vnc and set GET=1 for faster + connecting via HTTPS. + + A demo CGI script 'desktop.cgi' shows how to create an + SSL encrypted, multi-user x11vnc web login desktop + service. The user logs into a secure web site and gets + his/her own virtual desktop and his browser accesses it + with the SSL Java VNC Viewer applet. + + A serverCert Java Viewer applet parameter is provided. + Use an authenticated HTTPS browser connection to set + this parameter (the user could set it locally too.) + The onetimekey tool has -certonly option for this scheme. + + The Xdummy script (use Xorg 'dummy' driver instead of Xvfb) + no longer requires being run as root. + + + miscellaneous new features and changes: + + In the Java viewer applet, debugCerts and debugKeyboard parameters + are provided. The debugging output of the applet is more + readable. Some corner-case bugs (e.g. socket exceptions) + are now handled gracefully. Parameters forbid_Ctrl_Alt + and mapF5_to_atsign are added. + + The amount of time to wait for HTTPS applet downloads to finish + can be set in env. var. X11VNC_HTTPS_DOWNLOAD_WAIT_TIME. + + The -xkb mode is automatically enabled if there are more than + 4 keysyms per key. + + -coe is now an alias for -connect_or_exit. + + The -input_eagerly option enables this LibVNCServer feature + (it is like -allinput.) + + The "%" unix password verification tricks for the -unixpw + option are now documented. They also run a command + in UNIXPW_CMD. + + In -create (-svc, etc.) modes, a warning is printed out if Xvfb + cannot be found. Xvfb '+kb' option is checked for. + The -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt debugging + option is documented. Try to preserve user's PATH + if possible. + + In XDMCP connection mode, a test for GDM listening only + on IPv6 (::1) is performed. The interface can also be + specified via FD_XDMCP_IF. + + The example scripts connect_switch, ultravnc_repeater.pl, inet6to4 + have settings to let them run reliably for long times + as daemons. They also support IPv6. + + IPv6 notes: for some very esoteric cases (e.g. -chatwindow) + IPv4 localhost may be required for local IPC. A demo + transition tool 'inet6to4' is also included (can be + used for other apps.) x11vnc options related to IPv6: + -listen6, -6, -no6, -noipv4, -noipv6, and -connect, + -proxy. + + Use STUNNEL_LISTEN in -stunnel mode to have it listen on a + particular interface. Also STUNNEL_PROG. + + New remote control query options: pointer_x, pointer_y, + pointer_same, pointer_root, and pointer_mask. A demo + script using them misc/panner.pl is provided. + + Remote control change of -clip option will not create new + framebuffer if the size has not changed (for panner.pl) + + The X11VNC_DISABLE_SSL_CLIENT_MODE env. var. can be set to + disable SSL client role in reverse connections. This + means the VNC viewer side must be in SSL client role. + UltraVNC repeater operation can benefit from this. + + The SSL_INIT_TIMEOUT is increased to 1 hour if 'repeater' + is detected in a reverse connect string. + + The X property X11VNC_TRAP_XRANDR can be set on a desktop to + force x11vnc to use the -xrandr screen size change + trapping code. + + The -sslScripts option prints out the SSL certificate management + scripts. + + Suggest '-auth guess' and '-findauth' if X connection fails. + + The TightVNC sercurity type (TightVNC features enabler) now + works for RFB version 3.8. + + RECORD scroll detection is now working with the new gtk/gdk scroll + mechanism. Set X11VNC_SCROLL_MUST_EQUAL to disable. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.9 2009-12-21 + + + +New in the 0.9.9 x11vnc release: + + A new option -findauth runs the FINDDISPLAY script that applies + heuristics to try to determine the correct XAUTHORITY + file. The use of '-auth guess' will use the XAUTHORITY + that -findauth reveals. This can be handy in with + the lastest GDM where the ability to store cookies in + ~/.Xauthority has been removed. + + If x11vnc is running as root (e.g. inetd or XDM/GDM/KDM) + the FD_XDM=1 mode will be tried if the above -findauth + or '-auth guess' command fails; it will find the + correct XAUTHORITY for the given display (this works for + XDM/GDM/KDM if the login greeter panel is up or if someone + has already logged into an X session.) You can also + set -env FD_XDM=1 to force it to be done on the first try. + + The -unixpw_system_greeter option, when used in combined + unixpw and XDMCP FINDCREATEDISPLAY mode (e.g. -xdmsvc), + enables the user to press Escape to jump directly to the + XDM/GDM/KDM login greeter screen. This way the user + avoids entering his unix password twice at X session + creation time. For subseqent logins to the same session, + he uses the regular x11vnc unixpw "login:" prompt. Also, + the unixpw login panel now has a short help displayed + if the user presses 'F1' that lists the options. + + The -appshare option enables simple application sharing based on + the -id/-sid mechanism. Every new toplevel window that + the application creates induces a new viewer window via + a reverse connection. The -id/-sid and -connect options + are required. Run 'x11vnc -appshare -help' for more info. + + Heuristics are applied to try to determine if the X display + is currently in a Display Manager Greeter Login panel + (e.g. GDM.) If so, x11vnc's creation of any windows and + use of XFIXES are delayed. + + This is to try to avoid x11vnc being killed after the user + logs in if the GDM KillInitClients=true is in effect. + So one no longer needs to set KillInitClients=false in + gdm.conf. Note that in recent GDM the KillInitClients + option has been removed. + + Also delayed is the use of the XFIXES cursor fetching + functionality; this avoids an Xorg bug that causes Xorg + to crash right after the user logs in. + + x11vnc now tries to be more aggressive in keeping up with VNC + client's framebuffer update requests. Some broken VNC + clients continuously spray these requests at VNC servers + (regardless of whether they have received any updates + or not.) The -extra_fbur option allows one to fine tune + the setting. + + The "-display WAIT:cmd=...", -find, -create modes now work + correctly for the user-supplied login program scheme + "-unixpw_cmd ...", as long as the login program supports + running commands specified in the environment variable + "RFB_UNIXPW_CMD_RUN" as the logged-in user. The mode + "-unixpw_nis ..." has also been made more consistent. + The username option "tag=..." can be used to set FD_TAG. + + The -stunnel option (like -ssl but uses stunnel as an external + helper program) now works with the -ssl "SAVE" and "TMP" + special certificate names. The -sslverify and -sslCRL + options now work correctly in -stunnel mode. Single port + HTTPS connections are also supported for this mode. + + The remote control command -R can be used to instruct x11vnc + to resend its most recent copy of the Clipboard, + Primary, or Cutbuffer selections: "x11vnc -R + resend_clipboard", "x11vnc -R resend_primary", and + "x11vnc -R resend_cutbuffer". + + miscellaneous new features and changes: + + The fonts in the GUI (-gui) can now by set via environment + variables, e.g. -env X11VNC_FONT_BOLD='Helvetica -16 bold' + and -env X11VNC_FONT_FIXED='Courier -14'. + + The value of the -timeout option is now also used for the timing + out of reverse connections. The -timeout exit will + occur if no client has made it to normal operating state + (instead of merely trying to connect.) + + One can add extra URL parameters to the HTTPS (-ssl) urls + via X11VNC_EXTRA_HTTPS_PARAMS without needing to edit + index.vnc. E.g.: -env X11VNC_EXTRA_HTTPS_PARAMS='?GET=1' + + One can make the libvncserver HTTP (non-SSL) server listen on + localhost: -env X11VNC_HTTP_LISTEN_LOCALHOST=1 (this way + only the single-port VNC+HTTPS is exposed to the network.) + + Warnings are printed out at startup if $DISPLAY appears to + start with "localhost:" (SSH X11 forwarding) or + "hostname:" (remote X display; will fail w/o -noshm) + + The -solid option now uses the DBUS_SESSION_BUS_ADDRESS env. var + if available. The -solid option now works in xfce. + If available, the dbus_launch(1) will be used in + FINDCREATEDISPLAY for gnome sessions. + + The bcx_xattach remote control command was added to facilitate + xattach and x2x desktop cursor switching. Other new + remote control commands: grab_state, ping:mystring, + grablocal, resend_cutbuffer, resend_clipboard, + resend_primary, keycode, keysym, fakebuttonevent, + ptr, sleep, get_xprop, set_xprop, wininfo, pointer_pos, + mouse_xy, noop, guess_dbus, DIRECT:query. Remote control + scripting, -query_retries, and -remote_prefix were + also added. + + In -rawfb mode the X display will not be opened at all unless + the -rawfb string is prefixed with '+' or -display + was specified on the cmdline. + + For multiple, separate x11vnc instances on the same X display, + one can rename the X11VNC_REMOTE, X11VNC_TICKER, and + VNC_CONNECT property names to unique ones. + + The -showrfbauth option prints out the VNC rfbauth password. + + The XDAMAGE mechanism is now automatically disabled for a + period of time if a game or screensaver generates too + many XDAMAGE rectangles per second. This avoids the X11 + event queue from soaking up too much memory. + + x11vnc does not switch on server autorepeat if any keys are + pressed down to work around a recent Xorg server and/or + gnome bug where the key will never stop repeating. + + Thse list of current clients is kept more up-to-date in the + tkx11vnc gui. Bugs in the gui setpass mode have been + fixed. + + Threads stability is further improved. See under the -threads + option help info about -env X11VNC_THREADS_NEW_FB_SLEEP=ms + + There is an experimental workaround: "-env X11VNC_WATCH_DX_DY=1" + that tries to avoid problems with poorly constructed + menu themes that place the initial position of the mouse + cursor inside a menu item's active zone. + + The crypt(3) function is now declared inside the x11vnc code on + all platforms (not just Linux). To disable this, set + CPPFLAGS='-DDO_NOT_DECLARE_CRYPT' while configuring. + (crypt is declared to avoid problems with header files.) + + Error reasons are printed for -storepasswd failures. + + Two scripts are added to x11vnc/misc: connect_switch and + ultravnc_repeater.pl + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + + + +----------------------------------------------------------------------------- + + +x11vnc 0.9.8 2009-07-08 + + +New in the 0.9.8 x11vnc release: + + Better reliability for the Java Viewer applet when connecting + through a Web Proxy via HTTPS. A proxy hostname + and port can be specified via applet parameters. + Proxy Authentication via Auth-Basic is supported. + More x11vnc printout in -ssl is provided to help + troubleshoot this mode and other ssl connections. + + Stability improvements to -threads mode. Running x11vnc this + way is more reliable now. Threaded operation sometimes + gives better interactive response and faster updates. The + threaded mode now supports multiple VNC viewers using + the same VNC encoding (some only on Linux or enabled + at build time.) The threaded mode can also yield + a performance enhancement in the many client case + (e.g. class-room broadcast.) We have tested with 30 to + 50 simultaneous clients. See also -reflect. + + + miscellaneous new features and changes: + + x11vnc automatically tries to work around an Xorg server bug + involving infinitely repeating keys when turning off key + repeating. Use -repeat if the automatic workaround fails. + Also, the environment variable X11VNC_IDLE_TIMEOUT + (seconds) is provided. + + In -reflect mode the environment variable X11VNC_REFLECT_PASSWORD + is provided. + + The -clip mode works under -rawfb. + + The -nounixpw option can disable unixpw mode if an earlier option + enables it (e.g. -svc). + + Scroll detection is skipped for windows with 'OpenOffice' in + their name. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.7 2009-03-31 + + +New in the 0.9.7 x11vnc release: + + Basic support for building with VirtualGL's TurboVNC (an + enhanced TightVNC for fast LAN high framerate usage) + encoding and TightVNC modifications. More info: + http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc + and x11vnc/misc/turbovnc/README. + + The -ncache_cr option has been fixed and so in -ncache mode + smooth opaque window motions are now work correctly. Try + it out to see how smooth it is even on a slow link. + + Support for Linux text consoles (virtual terminals, e.g. 1-6) + is provided via, e.g., 'x11vnc -rawfb vt2' (for virtual + terminal #2). + + This is like LinuxVNC (i.e. text only), it avoids using + /dev/fb and uses /dev/vcsaN instead (the '-rawfb console' + mode uses /dev/fb.) With /dev/vcsaN the text terminal + is accessible even it if is not the currently active one. + + The -rawfb option now supports framebuffers with bits per pixel + less than 8 (e.g. 4 or 1 bpp.) + + Reverse connections now work in Anonymous Diffie Hellman SSL/TLS + mode. Reverse connections also work for VeNCrypt and + ANONTLS modes. + + + miscellaneous new features and changes: + + The included SSL enabled UltraVNC java viewer now has a + configurable [Home] entry in the drives drop down menu. + + In the -create, -svc, etc. modes one can now specify a + range of X displays to ignore in X11VNC_SKIP_DISPLAY. + Improvements and bugfixes were made to the find_display + and create_display scripts. FD_EXTRA option is provided. + + The '-rawfb video' option finds the video device file more + carefully. + + The -rmflag option allows a new way to indicate to other + applications that x11vnc has started. + + All of the java applet parameters are now documented in + the classes/ssl/README file. + + There is now a "sendbell" remote control command. + + A one-time -padgeom once:WxH mode is added. + + Improvements to the CUPS Terminal Services helper mode. + + If the X display cannot be opened normally then the env. var. + XAUTHLOCALHOSTNAME=localhost is tried. + + Bugfix for selection transfer to a now non-existent X window + (Thunderbird can cause this.) Related, the env. variable + LIBXCB_ALLOW_SLOPPY_LOCK is now set by default. + + Bugfix for -8to24 mode due to nonstandard indexed color support. + + The libvncserver and x11vnc autoconf/automake settings have + been improved. + + libXrandr include file is now found on Solaris. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.6 2008-12-10 + + +New in the 0.9.6 x11vnc release: + + x11vnc's SSL encryption is extended to support the VeNCrypt and + TLS (older; vino) SSL/TLS security type extensions to VNC. + + Anonymous Diffie-Hellman key exchange (-ssl ANON) and Certificate + Revocation List support (-sslCRL) is added to the SSL + encryption mode. + + The Java viewer applet can now be served up through the VNC port + (5900) in addition to the normal HTTP port (5800) via + the -http_oneport option. Previously this only worked + for SSL connections and HTTPS. + + The "-rfbport PROMPT" mode presents a simple gui for the user + to select a port for the x11vnc service and a few other + settings. This enables a menu entry for naive users + that is included in x11vnc.desktop. + + If x11vnc is not built with the Avahi Zeroconf library an external + helper program (avahi-publish or dns-sd on Mac OS X) + is used instead. + + miscellaneous new features and changes: + + The default mode for '-ssl' is now the '-ssl SAVE' mode; i.e. + the generated certificate is saved and reused in + subsequent sessions rather than being discarded. + Use '-ssl TMP' recover the old way. This change made + to for it to be more likely that the VNC Viewer can save + the accepted cert for future authentications. + + The solid background color option works on the Mac OS X console. + + The -reopen option enables x11vnc to try to re connect to the X + display if GDM (or other display manager) kills it just + after the user logs in. + + The -dhparams option can be used to point to your own Diffie + Hellman parameters. + + The -setdefer option allows tuning how quickly updates will + be sent. Default setting tuned. + + The option -zeroconf is now an alias for -avahi/-mdns. + + In pipeinput mode, the pipe filehandle is now closed when + x11vnc exits. + + The -sshonly option turns off VeNCrypt and TLSVNC (vino) mod + leaving only the standard SSL (i.e. vncs://) + + For testing, the option -rand in an alias for -rawfb rand -nopw + + Minor tweaks to improve CUPS Print tunneling. + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.5 2008-10-24 + + +New in the 0.9.5 x11vnc release: + + Symmetric key encryption using the RC4, AES, Blowfish, and 3DES + ciphers is supported via the -enc cipher:keyfile option. + The SSVNC unix viewer 1.0.20 and later supports these + encryption methods. + + Server-side scaling can now have different scale factors along + the horizontal and vertical axes. E.g. -scale 1280x1024 + (same as -geometry 1280x1024) or -scale 0.8x0.75 + + The -chatwindow option allows a chat window to appear on the + X console during UltraVNC chats (requires the SSVNC + viewer package.) + + miscellaneous new features and changes: + + The HTTP Java viewer applet jar, classes/VncViewer.jar, has + been updated with an improved implementation based on + the code used by the classes/ssl applets. + + A description and instructions are now printed out when + X_ShmAttach fails if one tries to attach to a remote + $DISPLAY (i.e. $DISPLAY is on a different machine from + the machine x11vnc is running on; this often happens + with SSH X redirection, X terminal servers, etc). + + The -allow option now works correctly in -ssl mode. + + The -remap option now works on the MacOSX console. + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.4 2008-09-17 + + +New in the 0.9.4 x11vnc release: + + Reverse VNC connections (-connect and -connect_or_exit options) + work in the -find and -create X session FINDCREATEDISPLAY + modes. + + Reverse VNC connections (either normal or using SSL) can use a + Web Proxy, a SOCKS proxy, the UltraVNC repeater proxy, + an SSH connection, or even a CGI URL to make the outgoing + connection (-proxy option). Forward connections can + use the -ssh option to set up a reachable redirection. + + Support for the ZYWRLE encoding is added, this is the RealVNC ZRLE + encoding extended to do motion video and photo regions + more efficiently by way of a Wavelet based transformation. + + The session finding and creating modes (-find and -create) have + been improved to be more reliable and also provide a new + desktop types (xfce) and new service redirection options. + + Support for indexed colormaps (PseudoColor) with depths other + than 8 is provided (depths 1 to 16 now work). + + Java viewer applet source code is provided in the x11vnc 0.9.4 + tarball so now everything can be built from source. + + miscellaneous new features and changes: + + To unset Caps_Lock, Num_Lock and raise all keys in the X server + use -clear_all, or by remote control 'x11vnc -R clear_all' + + The -autoport option gives more control over the server port + range that probes. + + The -ping option can be used to help keep idle connections alive. + + The -finddpy and -listdpy utilities help to debug and configure + the -find, -create, and -display WAIT:... modes. + + Some automatic detection of screen resizes are handled even if + the -xrandr option is not supplied. + + The -advertise_truecolor option can workaround some VNC viewer + incompatibilities with PseudoColor. + + The option '-clip xinerama0' can be used to clip to the first + Xinerama sub-screen, etc. + + If a fast framebuffer read rate is detected the -wait and -defer + parameters are reduced to 10 and 15 msec, respectively. + + Pasting of the selection/clipboard into remote applications + (e.g. Java) is improved. + + Usage with dvorak keyboards is improved. The option -macuskbd is + available on MacOSX to use the original US keyboard code. + + Via a compiler option (-DENABLE_GRABLOCAL) one can use the + -grablocal n option to filter VNC client input if someone + at the console has done mouse or keyboard input n secs ago. + + The -sleepin option can now sleep a random amount of time between + min and max time delays (-sleepin min-max). + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.3 2007-10-04 + + +New in the 0.9.3 x11vnc release: + + This release provides client-side caching to improve interactive + response. Almost no VNC viewers implement caching which is why + VNC is slow compared to other remote graphics protocols. + + The x11vnc caching will work with any VNC viewer, but they will + not hide the pixmap cache region that is below the main desktop + (one must adjust the window manually). The SSVNC Unix VNC viewer, + however, automatically detects and hides the region. + + To enable caching, supply "-ncache n" to x11vnc, where the + number n, e.g. 10, indicates how much memory to devote to the + caching scheme. + + See http://www.karlrunge.com/x11vnc/#faq-client-caching + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.2 2007-06-18 + + +New in the 0.9.2 x11vnc release: + + A compile-time bug is fixed for when the OpenSSL library is not + available or --without-ssl is supplied; previously the + build would fail. + + One can configure x11vnc via "configure --with-system-libvncserver" + to use a system installed libvncserver library instead of + the one bundled in the release tarball. + + If UltraVNC file transfer or chat is detected, then VNC clients + are "pinged" more often to prevent these side channels + from becoming serviced too infrequently. + + In -unixpw mode in the username and password dialog no text will + be echoed if the first character sent is "Escape". This + enables a convenience feature in SSVNC to send the username + and password automatically. + + miscellaneous new features and changes: + + When building from the CVS tree --with-x11vnc must be supplied if + you want x11vnc to be built. The LibVNCServer release + tarball no longer contains the x11vnc source. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9.1 2007-05-24 + + +New in the 0.9.1 x11vnc release: + + A new Unix username identification scheme is provided when + SSL client certificates are used to authenticate VNC + viewers. The username is extracted from the 'Subject' + section of the cert. The option is "-users sslpeer=" + which, like "-users unixpw=" already does, will cause + a switch to the Unix user. This is useful for the + -find and -create options that try to find an existing + X session associated with the user or create a new one. + + The UltraVNC Java Viewer has been modified to support SSL + connections. Some bugs were also fixed and some + improvements added. A patch file and a compiled jar file + (UltraViewerSSL.jar and SignedUltraViewerSSL.jar in the + classes/ssl directory) are provided in the x11vnc package. + + For the -user option groups are now handled better by using + initgroups(3), or if finer control is needed one can + use: "-users user1.group1,..." + + When SSL client certification is being used and external login + programs are being used the env. var. RFB_SSL_CLIENT_CERT + is set to the clients certificate. Set X11VNC_SSLPEER_CN + to use the Common Name instead of the certificate email + address to find the unix username. + + miscellaneous new features and changes: + + The -wait and -defer defaults were lowered from 30 to 20 + milliseconds, set the values explicitly if this increases + the load too much for your liking. + + In -create mode where a Xvfb session is started, mwm was added + as a session type. setpgrp(2) is used for the spawned + process if available. The XKEYBOARD extension is + enabled (+kb, but it doesn't seem to always work). + TrueColor is forced to be the default visual (recent + Xvfb seem to choose DirectColor, this is likely a bug) + One can also force creating a new Xvfb by setting the + env. var. X11VNC_FINDDISPLAY_ALWAYS_FAILS (not exactly + clear what this would be used for). + + The WAITBG env. var. enables -display WAIT:... to take place in + the background. + + One can specify the X11VNC_SKIP_DISPLAY env. var. for a list of + displays to exclude in the FINDDISPLAY action. This can + also be specified via nd=... as a -unixpw login option. + + setsid() or setpgrp() is called for the external command spawned + by the -gone option (since it may be long lived, e.g. a + screen locker). + + The script "onetimekey" utility is provided in the classes/ssl + subdirectory that allows a (very long) string representing + a Client SSL certificate to be provided by the authenticating + client, or via https cgi script (e.g. after a web login). + + Some bugs were fixed in the libvncserver implementation of + UltraVNC file transfer. + + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.9 2007-04-18 + + +New in the 0.9 x11vnc release: + + VNC Service advertising via mDNS / ZeroConf / BonJour with the + Avahi client library. Enable via "-avahi". + + Implementations of UltraVNC's TextChat, SingleWindow, and + ServerInput extensions (requires ultravnc viewer or ssvnc + Unix viewer). They toggle the selection of a single window + (-id), and disable (friendly) user input and viewing + (monitor blank) at the VNC server. + + Short aliases "-find", "-create", "-svc", and "-xdmsvc" for + commonly used FINDCREATEDISPLAY usage modes (to find + the user's display or create one, etc). + + Reverse VNC connections (viewer listening) now work in SSL + (-ssl) mode. + + miscellaneous new features and changes: + + New options to control the Monitor power state and keyboard/mouse + grabbing: -forcedpms, -clientdpms, -noserverdpms, + and -grabalways. + + A simple way to emulate inetd(8) to some degree via the "-loopbg" + option. + + Monitor the accuracy of XDAMAGE and apply "-noxdamage" if it is + not working well. OpenGL applications like like beryl and + MythTv have been shown to make XDAMAGE not work properly. + + For Java SSL connections involving a router/firewall port + redirection, an option -httpsredir to spare the user + from needing to include PORT=NNN in the browser URL. + + A -sleepin n option to delay startup by n seconds to let redirs + and listening clients to get started. + + TightVNC file transfer is now off by default; enable via + -tightfilexfer + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.8.4 2007-02-01 + + +New in the 0.8.4 x11vnc release: + + Native Mac OS X Aqua/Quartz support. It exports the full + display (no X11 server, etc). + + This provides an alternative to OSXvnc; some activities + are faster (and see the client-side caching feature + -ncache in the 0.8.5 development version for more + speedups). + + x11vnc can act as a VNC reflector/repeater using the + "-reflect host:N" option. This is useful for large + classroom broadcasting or demos. You set up a number + of reflectors to spread the network and CPU load around + for better response. + + A new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY -unixpw ..." + that will Create a new X session (Xvfb, Xdummy, or + Xorg) for the user if it cannot find the user's X + session display via the FINDDISPLAY method. It will + be re-found upon reconnection. + + This enables a simple "terminal services" mode based on + Unix username and password and where the user does not + have to memorize their VNC display number, etc. + + + miscellaneous new features and changes: + + Option -nodpms to avoid problems with programs like KDE's + kdesktop_lock that keep restarting the screen saver + every few seconds even with active VNC clients connected. + + The "-N" option couples the VNC Display number to the X Display + number. E.g. if your X DISPLAY is :2 then the VNC display + will be :2 (i.e. using port 5902). If that port is taken + x11vnc will exit. + + Wireframe copyrect detection for local user activity (e.g. someone + sitting at the physical display moving windows). You + can disable this with the -nowireframelocal option. + + To automatically fix the common mouse motion problem on XINERAMA + (multi-headed) displays, the -xwarppointer option is + enabled by default when XINERAMA is active. You can + disable this with the -noxwarppointer option. + + By default in -reflect mode -shared is implied (it makes sense), + use -noshared after the -reflect option to disable this. + + The -prog option lets you specify the full path (argv[0]) to + the program, in case it is spawned by inetd/tcpd and + cannot determine its path. The path is needed for the + -http option to guess the http classes directory. + + Usually not needed, but there are many options for tuning the + native Mac OS X mode: -macnodim -macnosleep -macnosaver + -macnowait -macwheel -macnoswap -macnoresize -maciconanim + -macmenu. + + An option -debug_xdamage has been added for debugging and profiling. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.8.3 2006-11-13 + + +New in the 0.8.3 x11vnc release: + + The -ssl option provides SSL encryption and authentication + natively via the www.openssl.org library. One can use + from a simple self-signed certificate server certificate + up to full CA and client certificate authentication schemes. + + The -sslverify option allows for authenticating VNC clients via + their certificates in either -ssl or -stunnel modes. + + Certificate creation and management tools are provide in the + -sslGenCert, -sslGenCA, and related options. + + An SSL enabled Java applet VNC Viewer applet is provided in + classes/ssl/VncViewer.jar. + + The applet may also be loaded into the web + browser via HTTPS, i.e one can use the VNC port, + e.g. https://host:5900/ + + See our "Enhanced TightVNC Viewer" project, for native + SSL enabled viewers. + + The -unixpw option supports Unix username and password + authentication. The -ssl or -localhost and -stunnel + options (or detection of an SSH tunnel) are enforced in + this mode to prevent password sniffing. + + Coupling -unixpw with -display WAIT:cmd=FINDDISPLAY provides a + way to allow a user to login with their UNIX password + and have their display connected to automatically. + + Hooks are provided in the -unixpw_cmd and "-passwdfile cmd:,custom:..." + options to allow you to supply your own authentication + and password lookup programs (e.g. LDAP). + + The "-ultrafilexfer" alias is provided and improved UltraVNC + filetransfer rates have been achieved. + + The -rotate option enables you to rotate or reflect the screen + before exporting via VNC. This is intended for use on + handhelds and other devices where the rotation orientation + is not "natural". + + miscellaneous new features and changes: + + Similar to -ssl, the -stunnel option starts up a SSL tunnel server + stunnel (that must be installed separately on the system) + to allow only encrypted SSL connections from the network. + + Option -sslnofail to exit immediately if there are any SSL + connection failures. + + A simpler variant of -unixpw is the -unixpw_nis option that + works in environments where the encrypted passwords are + readable, e.g. NIS. + + x11vnc can be configured and built to not depend on X11 libraries + "./configure --without-x" for -rawfb only operation + (e.g. embedded linux console devices). + + Add -cursor_drag to change the mouse cursor during Drag and Drop, etc. + + Under the "-connect_or_exit host" option x11vnc will exit + immediately unless the reverse connection to host + succeeds. The "-rfbport 0" option disables TCP listening + for connections (useful for this mode). + + The "-rawfb rand" and "-rawfb none" options are useful for + testing automation scripts, etc., without requiring a + full desktop. + + Reduced spewing of information at startup, use "-verbose" (also + "-v") to turn it back on for debugging. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.8.2 2006-07-13 + + +New in the 0.8.2 x11vnc release: + + Support for full mouse and keyboard input into the Linux + console framebuffer /dev/fb0 in -rawfb mode + (i.e. non-X11) by using the Linux "uinput" driver. + + This enables, for example, viewing and interacting + with Qt-embedded/Qtopia-Core apps on Linux-based + handhelds, etc. + + Options: -rawfb cons, -pipeinput UINPUT More info: + http://www.karlrunge.com/x11vnc/#faq-qt-embedded + + Extension of the display option: -display WAIT: + to delay x11vnc's opening of the X display + until a VNC client connects (useful built-in: + -display WAIT:cmd=FINDDISPLAY, to find a user's + display and Xauthority data). + + Options -grabkbd and -grabptr have x11vnc try to grab + the X display when VNC clients are connected to + prevent a (non-malicious) user at the physical X + display from performing keyboard or mouse input. + E.g. remote help-desk support. + + + miscellaneous new features and changes: + + -allowedcmds option to fine-tune which external commands + may be run by x11vnc, rather than shutting + them all off with -nocmds. + + -env VAR=VALUE convenience option to avoid the need of + setting environment variables before starting + x11vnc. + + -allinput option to enable libvncserver handleEventsEagerly + parameter (not clear it yields an improvement). + + -rawfb rand fun/testing option using /dev/urandom as a fb. + + -license, -copying, -warranty option. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.8.1 2006-06-03 + +New in the 0.8.1 x11vnc release: + + Improved support for webcams and tv tuners with video4linux + /dev/video: see the "-rawfb video" and "-pipeinput VID" + options. (the latter gives a simple keyboard control + of a tv tuner; see also the -freqtab option for stations). + + FBPM support for hardware that provides framebuffer power + management (it needs to be disabled when vnc clients + are connected). + + The -usepw option will require x11vnc to use a password of + some sort or otherwise exit immediately. Put it in + your ~/.x11vncrc so you don't forget. + + The command "x11vnc -storepasswd" will prompt for a password + without echoing and save it in ~/.vnc/passwd + + The X CLIPBOARD selection is managed in addition to the + X PRIMARY selection. + + + miscellaneous new features and changes: + + Convenience option for accessing the Linux console: -rawfb cons + etc. (requires /dev/fb0 to be working). + + clipboard/cut-text input can now be managed on a per-client + basis. + + -capslock and -skip_lockkeys options can help make CapsLock work + better. + + The Xdummy wrapper script is included in the source tree. + + A mode "-gone popup" as been added. + + -24to32 option to avoid 24bpp problems. + + -xinerama is on by default. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.8 2006-02-13 + + +New in the 0.8 x11vnc release: + + TightVNC file transfer support is enabled via the extension to + LibVNCServer added by Rohit Kumar. + + The -passwdfile option has been enhanced to handle any number + of full-access and view only passwords in an easy to + maintain format, and additional features. + + The -8to24 option enables multi-depth viewing on systems that do + not support -overlay. The 8bpp regions are transformed + to depth 24 TrueColor before exporting via VNC. + + The x11vnc source code has gone through a major reorganization. + The build has been enhanced and many bugs fixed. + + + miscellaneous new features and changes: + + -afteraccept option is like -accept however it enables running + a user supplied command after client authentication + has taken place. The RFB_* environment variables have + been extended. + -loop option will run x11vnc in an outer loop restarting each time + (useful for situations where the X server restarts often). + -slow_fb allows for slow polling for special purpose applications + (e.g. video). -blackout noptr,WxH+X+Y,... will prevent + the pointer from going into a blacked out region. + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help | less + +----------------------------------------------------------------------------- + + +x11vnc 0.7.2 2005-07-11 + + +New in the 0.7.2 x11vnc release: + + The X DAMAGE extension is supported to dramatically reduce + resource consumption when idle: often 20 times less; + and to pick up small changed regions more quickly. + + DAMAGE sends events indicating damaged (modified) screen + rectangles to x11vnc. These are used as hints to focus + the polling and also if the rectangle is below a size + threshold it is accepted unconditionally (i.e. dragged in + from the framebuffer). Tuning is possible with -xd_area. + + DAMAGE is available on recent Xorg servers and Solaris 10. + + -wireframe: Heuristics are used to guess when a window is being + moved or resized and during this period show only a + moving wireframe outline. Just like on video cards in + the 90's, remember? This is to avoid window "lurching" + when you move or resize one opaquely. + + Also, -wirecopyrect applies the VNC CopyRect encoding + for the moved window. Both are on by default, use + -nowireframe or -nowirecopyrect to disable (aka -nowf + and -nowcr). + + -scrollcopyrect: Sniff the X11 protocol via the RECORD extension + and to try to detect window scrolls (e.g. via scrollbar, + Up/Down arrow, etc). When detected, the VNC CopyRect + encoding is applied to the scrolled regions for a speedup. + + The contents of the scrolling window may only be + approximate while it is being scrolled: e.g. tearing, + bunching-up, etc. The heuristics will also miss scrolls + by certain toolkits or applications, so those will still + happen the slow way. To disable use -noscrollcopyrect + (aka -noscr). Tuning is also available, see the -help + entry. + + -listen: Makes x11vnc listen only on a single network interface. + -localhost now implies '-listen localhost'. + + -rawfb: Instead of polling an X server framebuffer, poll a raw + one (i.e. a mapped file or a shm segment). E.g. for + the linux framebuffer device: + + -rawfb map:/dev/fb0@1024x768x32 + + This is a bit out of x11vnc's scope but may have some + interesting applications. Perhaps /dev/video? + + -pipeinput: Pipe the VNC user's pointer and keyboard input events + to a helper program you provide. Two examples are in + misc/vcinject.pl and misc/slide.pl. Primarily intended + for use with -rawfb to somehow kludge-up user input, + but it can also be used by itself. + + Improvements for the magnification scaling case (e.g. -scale 2) + for use in low vision applications. It is faster and + no-blending :nb now works correctly. + + More safety measures are taken WRT remote-control in the + default mode. See the -unsafe, -safer, -privremote, + and -nocmds options. + + The GUI has been improved, and running with the options "-gui icon" + presents a small, simple gui instead of the full blown one, + and "-gui tray" attempts to embed the small icon in the + system tray. Use "-gui tray=setpass" to prompt for + session password creation at startup. + + + miscellaneous new features and changes: + + -xkb: a simple test is performed at startup to see if it is a + good idea to apply -xkb mode for the current keyboard + keymapping (i.e. if keysyms like !, @, [ are otherwise + unavailable). To disable use -noxkb. + ISO_Level3_Shift vs. Mode_switch: Set things up in -xkb mode to + prefer ISO_Level3_Shift over Mode_switch for modtweaking. + No override; let me know if this causes problems. + -add_keysyms is now the default, use -noadd_keysyms to disable. + the added keysyms are periodically deleted. + -remap DEAD: shorthand for mapping many "dead" keysyms to their + "un-dead" counterparts, e.g. grave -> dead_grave. For + some VNC viewers that are unable to send the dead keysym. + -skip_dups: skip impossible duplicate key events sent by some VNC + viewers. -noskip_dups to disable (currently off by default). + -sloppy_keys: try to handle sloppy keyboarding (esp. between + different language keyboards) where, say, Shift is released + before the key. + -norepeat N: ping-pong N times if something else on the desktop + restores key autorepeating (e.g. session startup). Default + 2. Also, If the VNC client is idle for 5 min. autorepeat + is restored. + -wait_ui: If there is very recent user input, cut the -wait sleep + time by the specified factor (default 2.0). + -nowait_bog: Detection is now in place to watch for polling "bogging + down" (e.g. lots of scrolling text from a long build in a + terminal) and to sleep more. Use -nowait_bog to disable. + -flag: write PORT=5900 to a flag file to aid wrapper scripts. + -http: try to guess what the -httpdir should be and if found + enable http listening. + -clip WxH+X+Y: only show the specified rectangle not the + entire screen. + cursors are now scaled by default under -scale, use -scale_cursor + to modify this behavior. + -arrow n: select from some different arrow cursors (ignored under + XFIXES cursor grabbing mode). + -nolookup: disable DNS lookups for broken environments. + -seldir: fine tune and debug selection transfer. + build-time customization macros: SHARED, FOREVER, NOREPEAT, + REMOTE_CONTROL, SMALL_FOOTPRINT, default passwd, etc. + see the top of the x11vnc.c for more info. + -xtrap: DEC-XTRAP extension is supported for legacy systems + with insufficient XTEST extension (X11R5). + -shiftcmap: for legacy systems with non-standard colormap values. + -noxrecord: do not use the RECORD extension for anything (currently + only -scrollcopyrect and grabserver watching use it). + -grab_buster: fork a helper thread to watch for XGrabServer deadlock + in x11vnc and break the grab. Under -scrollcopyrect there + is a small window where x11vnc is vulnerable to this deadlock. + -dbg: A "crash shell" with tips on debugging will be presented + instead of exiting when a fatal error occurs. + -fixscreen: periodically refresh the screen to get rid of painting + errors, etc. induced by new features, jpeg compression, etc. + -speeds: Tell x11vnc what the network and fb speeds are instead of + having it try to measure them. (these speeds are used by + various features, such as -wireframe, -scrollcopyrect, etc.). + -wmdt: set the window manager or desktop to spare x11vnc from guessing. + -readtimeout: set libvncserver's read timeout parameter, useful on + very slow links that take more than 20secs to paint + the whole screen. + -nopw: If you use x11vnc without a password it now prints out a + scary warning message. Use -nopw to disable the warning. + plugged X event leaks; periodically purge any remaining buildup. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help + +----------------------------------------------------------------------------- + + +x11vnc 0.7.1 2005-02-24 + + +New in the 0.7.1 x11vnc release: + + Improved algorithm for approximating XFIXES cursors with + transparency (alpha channel). No more ugly black fuzz + around translucent cursors. Tuning parameters -alpha* + if it is still not right. + + Added mechanisms to handle XFIXES cursors with transparency + exactly (i.e. blend in the background). Works by default + under -nocursorshape updates, and also works under limited + circumstances for cursorshape updates if the VNC viewer + is patched (TightVNC viewer patch provided). + + -solid: to improve performance switch the background to a solid + color when clients are connected. Works on GNOME, KDE, + CDE, and classic X. + + -input: allows fine-tuning the type of allowed user input + (Keystroke, Mouse-motion, Button-click). Useful for + certain applications of x11vnc, e.g. demos. Also + per-client settings via -R input:xyz.. + + -users: enables switching to different users if started as root. + Please read the description for details. + + -gui ez: less daunting GUI with fewer options via '-gui ez' or + "Misc -> simple-gui" once started. + + miscellaneous new features and changes: + + -nap is now the default, use -nonap to disable. + -snapfb: snapshot h/w fb to RAM periodically, not clear how useful... + -timeout n: for use in certain applications, exit if no client + connects after n seconds. + -oa and -logappend for appending to logfiles. + -opts will just show the options w/o the long -help descriptions. + if you forget to set -display, it will beep and try :0 after a bit. + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help + +----------------------------------------------------------------------------- + + +x11vnc 0.7 2004-12-23 + + +New in the 0.7 x11vnc release: + + Support for the XFIXES X extension to show the exact mouse cursor + shape. Requires libXfixes. For approximate cursor + shapes also see: -cursor (none|arrow|X|some|most) + + -remote/-R: remote-control support: nearly every setting can be + changed dynamically without restarting x11vnc. For + example, "x11vnc -R shared", and "x11vnc -R scale:3/4" + will connect to a running x11vnc server to make it shared + and re-scaled, respectively. + + -gui: launches a simple tcl/tk GUI based on the remote control + function. Requires the tcl/tk "wish" program. + + -overlay: support for overlay/multi-depth (e.g. 24+8) visuals + on Solaris (SUN_OVL extension) and IRIX. + + -xrandr: support for the XRANDR (X Resize, Rotate and Reflection) + extension: if the screen changes size or rotates x11vnc + creates a new framebuffer to match it. Useful to have a VNC + Viewer that supports NewFBSize extension. (also -padgeom) + + -pointer_mode: Experimental pointer input handling schemes, + e.g.: "-pointer_mode 3" (similar to -nodragging) + + man page x11vnc.1 and README files created. + + miscellaneous new features and changes: + + -sb: set screen blank idle timeout + -nocursorshape: disable cursor shape VNC extension. + RFB_MODE = "accept" or "gone" passed to -accept/-gone commands. + -vncconnect is now the default. + -norepeat is now the default. + "-id pick" to pick a window via xwininfo for the -id option. + -sid option: like -id but crops root window instead. + Related to remote-control: -query, -noremote, -sync, + -deny_all, -safer, -unsafe. + + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help + +----------------------------------------------------------------------------- + + +x11vnc 0.6.2 2004-08-02 + +New in the 0.6.2 x11vnc release: + + -scale option for server side scaling (e.g. -scale 2/3). + + -storepasswd option to create VNC password files. + + ~/.x11vncrc simple config file support. + + -cursorpos now the default (send cursor position updates to clients + that understand them, disable with -nocursorpos) + + more connection info sent to the -accept and -gone commands. + + new keyboard related features: + + -modtweak is now the default (it automatically adjusts the modifier + keys state to send a Keysym properly, disable -nomodtweak) + this works around "ghost" keys like "< >" in XFree86. + + -xkb option to use XKEYBOARD extension for modtweak-ing to further + improve the accuracy of sending Keysyms between different + language keyboards. + + -skip_keycodes and -add_keysyms options to fine tune stubborn + keyboard differences. + + -norepeat option to turn off X server key autorepeat when clients + are connected (works around the repeated characters problem) + + -clear_mods and -clear_keys to send key release events at + startup and exit. + + removed options: + + -hints/-nohints: we now always use hints. + +For more information: + + http://www.karlrunge.com/x11vnc/ + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + x11vnc -help + +----------------------------------------------------------------------------- + diff --git a/x11vnc/appshare.c b/x11vnc/appshare.c index fc3c29e..71cdf17 100644 --- a/x11vnc/appshare.c +++ b/x11vnc/appshare.c @@ -1358,7 +1358,7 @@ static void list_apps(void) { static int process_control(char *file, int check_clients) { int i, nnew = 0, seen[CMAX]; - char line[1024], *new[CMAX]; + char line[1024], *newctl[CMAX]; FILE *f; f = fopen(file, "r"); @@ -1481,7 +1481,7 @@ static int process_control(char *file, int check_clients) { if (idx >= 0) { seen[idx] = 1; } else { - new[nnew++] = strdup(q); + newctl[nnew++] = strdup(q); } } } @@ -1509,8 +1509,8 @@ static int process_control(char *file, int check_clients) { } continue; } - clients[free] = new[i]; - client(new[i], 1); + clients[free] = newctl[i]; + client(newctl[i], 1); } } return 1; diff --git a/x11vnc/cleanup.c b/x11vnc/cleanup.c index 4ecef42..232311c 100644 --- a/x11vnc/cleanup.c +++ b/x11vnc/cleanup.c @@ -50,6 +50,7 @@ so, delete this exception statement from your version. #include "screen.h" #include "xrecord.h" #include "xevents.h" +#include "uinput.h" /* * Exiting and error handling routines @@ -187,6 +188,8 @@ void clean_up_exit(int ret) { pipeinput_fh = NULL; } + shutdown_uinput(); + if (! dpy) { /* raw_rb hack */ if (rm_flagfile) { unlink(rm_flagfile); diff --git a/x11vnc/gui.c b/x11vnc/gui.c index e264385..6101adb 100644 --- a/x11vnc/gui.c +++ b/x11vnc/gui.c @@ -81,26 +81,26 @@ static Window tweak_tk_window_id(Window win) { return None; #else char *name = NULL; - Window parent, new; + Window parent, new_win; if (getenv("NO_TWEAK_TK_WINDOW_ID")) { return win; } /* hack for tk, does not report outermost window */ - new = win; + new_win = win; parent = parent_window(win, &name); if (parent && name != NULL) { lowercase(name); if (strstr(name, "wish") || strstr(name, "x11vnc")) { - new = parent; + new_win = parent; rfbLog("tray_embed: using parent: %s\n", name); } } if (name != NULL) { XFree_wr(name); } - return new; + return new_win; #endif /* NO_X11 */ } diff --git a/x11vnc/help.c b/x11vnc/help.c index 5eb80cc..c268b3f 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -848,6 +848,12 @@ void print_help(int mode) { " Some degree of cooperation from the person at the\n" " display is assumed. This is intended for remote\n" " help-desk or educational usage modes.\n" +"\n" +" Note: on some recent (12/2010) X servers and/or\n" +" desktops, -grabkbd no longer works: it prevents the\n" +" window manager from resizing windows and similar things.\n" +" Try -ungrabboth below (might not work.)\n" +"\n" "-grabptr As -grabkbd, but for the mouse pointer using\n" " XGrabPointer(3X11). Unfortunately due to the way the X\n" " server works, the mouse can still be moved around by the\n" @@ -857,6 +863,11 @@ void print_help(int mode) { " act on the local user's input. Again, some degree of\n" " cooperation from the person at the display is assumed.\n" "\n" +"-ungrabboth Whenever there is any input (either keyboard or\n" +" pointer), ungrab *both* the keyboard and the pointer\n" +" while injecting the synthetic input. This is to allow\n" +" window managers, etc. a chance to grab.\n" +"\n" "-grabalways Apply both -grabkbd and -grabptr even when no VNC\n" " viewers are connected. If you only want one of them,\n" " use the -R remote control to turn the other back on,\n" @@ -1412,6 +1423,15 @@ void print_help(int mode) { "\n" " xauth extract - $DISPLAY\"\n" "\n" +" NOTE: As specified in the previous paragraph, you can\n" +" supply your own WAIT:cmd=... program or script, BUT\n" +" there are two very useful *BUILT-IN* ones: FINDDISPLAY\n" +" (alias -find above) and FINDCREATEDISPLAY (alias -create\n" +" above.) Most people use these instead of creating\n" +" their own script. Read the following (especially the\n" +" BUILT-IN modes sections) to see how to configure these\n" +" two useful builtin -display WAIT: modes.\n" +"\n" " In the case of -unixpw (and -unixpw_nis only if x11vnc\n" " is running as root), then the cmd= command is run\n" " as the user who just authenticated via the login and\n" @@ -1443,6 +1463,11 @@ void print_help(int mode) { " your long \"login:\" line press the Up arrow once\n" " (before typing anything else).\n" "\n" +" Most of these colon options only apply to the builtin\n" +" FINDDISPLAY and FINDCREATEDISPLAY modes, but note\n" +" that they are passed to the extrenal command in the\n" +" environment as well and so could be used.\n" +"\n" " In the login panel, press F1 to get a list of the\n" " available options that you can add after the username.\n" "\n" @@ -1476,23 +1501,19 @@ void print_help(int mode) { " and the user put \"geom=1600x1200\" in his\n" " ~/.x11vnc_create file.\n" "\n" -" To troubleshoot the FINDCREATEDISPLAY mechanism,\n" -" set the following env. var. to an output log file,\n" -" e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt\n" -"\n" " To disable the option setting set the environment\n" " variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc.\n" " To set any other options, the user can use the gui\n" " (x11vnc -gui connect) or the remote control method\n" " (x11vnc -R opt:val) during his VNC session.\n" "\n" -" The combination of -display WAIT:cmd=... and -unixpw\n" -" allows automatic pairing of an unix authenticated VNC\n" -" user with his desktop. This could be very useful on\n" -" SunRays and also any system where multiple users share\n" -" a given machine. The user does not need to remember\n" -" special ports or passwords set up for his desktop\n" -" and VNC.\n" +" So we see the combination of -display WAIT:cmd=... and\n" +" -unixpw allows automatic pairing of an unix\n" +" authenticated VNC user with his desktop. This could\n" +" be very useful on SunRays and also any system where\n" +" multiple users share a given machine. The user does\n" +" not need to remember special ports or passwords set up\n" +" for his desktop and VNC.\n" "\n" " A nice way to use WAIT:cmd=... is out of inetd(8)\n" " (it automatically forks a new x11vnc for each user).\n" @@ -1504,13 +1525,15 @@ void print_help(int mode) { " process that will not switch, but it is only encoding\n" " and decoding the encrypted stream at that point.\n" "\n" -" Automatic Finding of User X Sessions:\n" +" BUILT-IN modes:\n" +"\n" +" -- Automatic Finding of User X Sessions --\n" "\n" " As a special case, WAIT:cmd=FINDDISPLAY will run a\n" " script that works on most Unixes to determine a user's\n" " DISPLAY variable and xauthority data (see who(1)).\n" "\n" -" The option \"-find\" is an alias for this mode.\n" +" NOTE: The option \"-find\" is an alias for this mode.\n" "\n" " To have this default script printed to stdout (e.g. for\n" " customization) run with WAIT:cmd=FINDDISPLAY-print To\n" @@ -1553,7 +1576,12 @@ void print_help(int mode) { " X11VNC_SKIP_DISPLAY=all then all display finding fails\n" " as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.)\n" "\n" -" Automatic Creation of User X Sessions:\n" +" On some systems lsof(1) can be very slow. Set the\n" +" env. var. FIND_DISPLAY_NO_LSOF=1 to skip using lsof to\n" +" try to find the Linux VT the X server is running on.\n" +" set FIND_DISPLAY_NO_VT_FIND=1 to avoid looking at all.\n" +"\n" +" -- Automatic Creation of User X Sessions --\n" "\n" " An interesting option is WAIT:cmd=FINDCREATEDISPLAY\n" " that is like FINDDISPLAY in that is uses the same method\n" @@ -1562,13 +1590,19 @@ void print_help(int mode) { " for the user. This is the only time x11vnc tries to\n" " actually start up an X server.\n" "\n" -" The option \"-create\" is an alias for this mode.\n" +" NOTE: The option \"-create\" is an alias for this mode.\n" "\n" " It will start looking for an open display number at :20\n" " Override via X11VNC_CREATE_STARTING_DISPLAY_NUMBER=n\n" " By default 80 X displays are allowed (i.e. going to :99)\n" " Override via X11VNC_CREATE_MAX_DISPLAYS=n\n" "\n" +" For its heuristics, the create display script sets\n" +" LC_ALL=C so that command output is uniform. By default\n" +" it will try to restore LC_ALL right before starting the\n" +" user session. However, if you don't mind it keeping\n" +" LC_ALL=C set the env. var.: X11VNC_CREATE_LC_ALL_C_OK=1\n" +"\n" " By default FINDCREATEDISPLAY will try Xvfb and then\n" " Xdummy:\n" "\n" @@ -1595,6 +1629,10 @@ void print_help(int mode) { " it to terminate (or kill the X server process if all\n" " else fails).\n" "\n" +" To troubleshoot the FINDCREATEDISPLAY mechanism,\n" +" set the following env. var. to an output log file,\n" +" e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt\n" +"\n" " So this is a somewhat odd mode for x11vnc in that it\n" " will start up and poll virtual X servers! This can\n" " be used from, say, inetd(8) to provide a means of\n" @@ -4075,6 +4113,7 @@ void print_help(int mode) { "-sb time Time in seconds after NO activity (e.g. screen blank)\n" " to really throttle down the screen polls (i.e. sleep\n" " for about 1.5 secs). Use 0 to disable. Default: %d\n" +" Set the env. var. X11VNC_SB_FACTOR to scale it.\n" "\n" "-readtimeout n Set LibVNCServer rfbMaxClientWait to n seconds. On\n" " slow links that take a long time to paint the first\n" @@ -4520,18 +4559,19 @@ void print_help(int mode) { " using the 'console_guess' string printed at startup,\n" " be sure to indicate the snap: method.\n" "\n" -" uinput: If the Linux version appears to be 2.6 or\n" -" later and the \"uinput\" module appears to be present\n" -" (modprobe uinput), then the uinput method will be used\n" -" instead of /dev/ttyN. uinput allows insertion of BOTH\n" -" keystrokes and mouse input and so it preferred when\n" -" accessing graphical (e.g. QT-embedded) linux console\n" -" apps. See -pipeinput UINPUT below for more information\n" -" on this mode; you will have to use -pipeinput if you\n" -" want to tweak any UINPUT parameters. You may also want\n" -" to also use the -nodragging and -cursor none options.\n" -" Use \"console0\", etc or -pipeinput CONSOLE to force\n" -" the /dev/ttyN method.\n" +" uinput: If the Linux version appears to be 2.6\n" +" or later and the \"uinput\" module appears to be\n" +" present (modprobe uinput), then the uinput method\n" +" will be used instead of /dev/ttyN. uinput allows\n" +" insertion of BOTH keystrokes and mouse input and so it\n" +" preferred when accessing graphical (e.g. QT-embedded)\n" +" linux console apps. It also provides more accurate\n" +" keystroke insertion. See -pipeinput UINPUT below for\n" +" more information on this mode; you will have to use\n" +" -pipeinput if you want to tweak any UINPUT parameters.\n" +" You may also want to also use the -nodragging and\n" +" -cursor none options. Use \"console0\", etc or\n" +" -pipeinput CONSOLE to force the /dev/ttyN method.\n" "\n" " Note you can change the Linux VT remotely using the\n" " chvt(1) command to make the one you want be the active\n" @@ -4571,7 +4611,11 @@ void print_help(int mode) { " to improve performance in the case of many (e.g. >\n" " 10) simultaneous VNC viewers, and you try a divide\n" " and conquer scheme to reduce bandwidth and improve\n" -" responsiveness.\n" +" responsiveness. (However, another user found this mode\n" +" useful to export a demo display through a slow link:\n" +" then multiple demo viewers connected to the reflecting\n" +" x11vnc on the fast side of the link, and so avoided\n" +" all of the demo viewers going through the slow link.)\n" "\n" " For example, if there will be 64 simultaneous VNC\n" " viewers this can lead to a lot of redundant VNC traffic\n" @@ -4602,6 +4646,13 @@ void print_help(int mode) { " to \"file:path_to_file\" to indicate a file containing\n" " the password as its first line.\n" "\n" +" To set the pixel format that x11vnc requests as a VNC\n" +" CLIENT set the env. vars: X11VNC_REFLECT_bitsPerSample\n" +" X11VNC_REFLECT_samplesPerPixel, and\n" +" X11VNC_REFLECT_bytesPerPixel; the defaults are 8, 3, 4.\n" +" 2, 3, 1 would give a low color mode. See the function\n" +" rfbGetClient() in libvncclient for more info.\n" +"\n" " The VNC HOST mode implies -shared. Use -noshared as\n" " a subsequent cmdline option to disable sharing.\n" "\n" @@ -4664,7 +4715,8 @@ void print_help(int mode) { "\n" " The UINPUT mode currently only does US keyboards (a\n" " scan code option may be added), and not all keysyms\n" -" are supported.\n" +" are supported. But it is probably more accurate than\n" +" the \"CONSOLE\" method.\n" "\n" " You may want to use the options -cursor none and\n" " -nodragging in this mode.\n" @@ -4704,16 +4756,6 @@ void print_help(int mode) { " cause jerkiness or unexpected behavior with menus, etc.\n" " Use reset=0 to disable.\n" "\n" -" If the uinput device has an absolute pointer (as opposed\n" -" to a normal mouse that is a relative pointer) you can\n" -" specify the option \"abs\". Note that a touchpad\n" -" on a laptop is an absolute device to some degree.\n" -" This (usually) avoids all the problems with mouse\n" -" acceleration. If x11vnc has trouble deducing the size\n" -" of the device, use \"abs=WxH\". Furthermore, if the\n" -" device is a touchscreen (assumed to have an absolute\n" -" pointer) use \"touch\" or \"touch=WxH\".\n" -"\n" " If you set the env. var X11VNC_UINPUT_THRESHOLDS then\n" " the thresh=n mode will be enabled. It is currently\n" " not working well. If |dx| <= thresh and |dy| < thresh\n" @@ -4723,8 +4765,70 @@ void print_help(int mode) { " Example:\n" " -pipeinput UINPUT:accel=4.0 -cursor none\n" "\n" -" You can also set the env. var X11VNC_UINPUT_DEBUG=1 or\n" -" higher to get debugging output for UINPUT mode.\n" +" If the uinput device has an absolute pointer (as opposed\n" +" to a normal mouse that is a relative pointer) you can\n" +" specify the option \"abs\". Note that a touchpad\n" +" on a laptop is an absolute device to some degree.\n" +" This (usually) avoids all the problems with mouse\n" +" acceleration. If x11vnc has trouble deducing the\n" +" size of the device, use \"abs=WxH\". Furthermore,\n" +" if the device is a touchscreen (assumed to have an\n" +" absolute pointer) use \"touch\" or \"touch=WxH\".\n" +" For touchscreens, when a mouse button is pressed,\n" +" a pressure increase is injected, and when the button\n" +" is released a pressure of zero is injected.\n" +"\n" +" If touch has been set, use \"touch_always=1\" to\n" +" indicate whenever the mouse moves with no button\n" +" pressed, a touch event of zero pressure should be\n" +" sent anyway. Also use \"btn_touch=1\" to indicate a\n" +" BTN_TOUCH keystroke press or release should be sent\n" +" instead of a pressure change. Set \"dragskip=n\" to\n" +" skip n dragged mouse touches (with pressure applied)\n" +" before injecting one. To indicate the pressure that\n" +" should be sent when there is a button click for a\n" +" touchscreen device, specify pressure=n, e.g. n=5. The\n" +" default is n=1.\n" +"\n" +" If a touch screen is being used (\"touch\" above)\n" +" and it is having its input processed by tslib, you can\n" +" specify the tslib calibration file via tslib_cal=.\n" +" For example, tslib_cal=/etc/pointercal. To get accurate\n" +" or even usable positioning this is required when tslib\n" +" is in use.\n" +"\n" +" The Linux uinput mechanism can be bypassed and one can\n" +" write input events DIRECTLY to the devices instead.\n" +" To do this, specify one or more of the following\n" +" for the input classes: direct_rel=\n" +" direct_abs= direct_btn= or\n" +" direct_key=. The file is usually\n" +" something like /dev/input/event1 but you can specify\n" +" any device file or pipe. You must specify each one\n" +" of the above classes even if they correspond to the\n" +" same device file (rel/abs and btn are often the same.)\n" +" Look at the file /proc/bus/input/devices to get an idea\n" +" what is available and the device filenames. Note:\n" +" The /dev/input/mouse* devices do not seem to work,\n" +" use the corresponding /dev/input/event* file instead.\n" +" Any input class not directly specified as above will be\n" +" handled via the uinput mechanism. To disable creating a\n" +" uinput device (and thereby discarding unhandled input),\n" +" specify \"nouinput\".\n" +"\n" +" Examples:\n" +"\n" +" -pipeinput UINPUT:direct_abs=/dev/input/event1\n" +"\n" +" this was used on a qtmoko Neo freerunner (armel):\n" +"\n" +" -pipeinput UINPUT:touch,tslib_cal=/etc/pointercal,\n" +" direct_abs=/dev/input/event1,nouinput,dragskip=4\n" +"\n" +" (where the long line has been split into two.)\n" +"\n" +" You can set the env. var X11VNC_UINPUT_DEBUG=1 or higher\n" +" to get debugging output for UINPUT mode.\n" "\n" "-macnodim For the native MacOSX server, disable dimming. \n" "-macnosleep For the native MacOSX server, disable display sleep.\n" diff --git a/x11vnc/keyboard.c b/x11vnc/keyboard.c index 9e9e044..54ff70e 100644 --- a/x11vnc/keyboard.c +++ b/x11vnc/keyboard.c @@ -61,7 +61,7 @@ void check_add_keysyms(void); int add_keysym(KeySym keysym); void delete_added_keycodes(int bequiet); void initialize_remap(char *infile); -int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new); +int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new_kc); void switch_to_xkb_if_better(void); char *short_kmbcf(char *str); void initialize_allowed_input(void); @@ -518,7 +518,7 @@ int add_keysym(KeySym keysym) { for (kc = minkey+1; kc <= maxkey; kc++) { int i, j, didmsg = 0, is_empty = 1; char *str; - KeySym new[8]; + KeySym newks[8]; for (n=0; n < syms_per_keycode; n++) { if (keymap[ (kc-minkey) * syms_per_keycode + n] @@ -532,19 +532,19 @@ int add_keysym(KeySym keysym) { } for (i=0; i<8; i++) { - new[i] = NoSymbol; + newks[i] = NoSymbol; } if (add_keysyms == 2) { - new[0] = keysym; /* XXX remove me */ + newks[0] = keysym; /* XXX remove me */ } else { for(i=0; i < syms_per_keycode; i++) { - new[i] = keysym; + newks[i] = keysym; if (i >= 7) break; } } XChangeKeyboardMapping(dpy, kc, syms_per_keycode, - new, 1); + newks, 1); if (alltime_num >= alltime_len) { didmsg = 1; /* something weird */ @@ -584,7 +584,7 @@ static void delete_keycode(KeyCode kc, int bequiet) { #else int minkey, maxkey, syms_per_keycode, i; KeySym *keymap; - KeySym ksym, new[8]; + KeySym ksym, newks[8]; char *str; RAWFB_RET_VOID @@ -594,10 +594,10 @@ static void delete_keycode(KeyCode kc, int bequiet) { &syms_per_keycode); for (i=0; i<8; i++) { - new[i] = NoSymbol; + newks[i] = NoSymbol; } - XChangeKeyboardMapping(dpy, kc, syms_per_keycode, new, 1); + XChangeKeyboardMapping(dpy, kc, syms_per_keycode, newks, 1); if (! bequiet && ! quiet) { ksym = XKeycodeToKeysym(dpy, kc, 0); @@ -907,14 +907,14 @@ static int kc1_shift, kc1_control, kc1_caplock, kc1_alt; static int kc1_meta, kc1_numlock, kc1_super, kc1_hyper; static int kc1_mode_switch, kc1_iso_level3_shift, kc1_multi_key; -int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new) { +int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new_kc) { if (!sloppy_keys) { return 0; } RAWFB_RET(0) #if NO_X11 - if (!key || !down || !keysym || !new) {} + if (!key || !down || !keysym || !new_kc) {} return 0; #else @@ -958,7 +958,7 @@ int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new) { "-> %d/0x%x (nmods: %d)\n", (int) key, (int) key, downkey, downkey, nmods_down); } - *new = downkey; + *new_kc = downkey; return 1; } } diff --git a/x11vnc/keyboard.h b/x11vnc/keyboard.h index e72cb86..39a1a89 100644 --- a/x11vnc/keyboard.h +++ b/x11vnc/keyboard.h @@ -48,7 +48,7 @@ extern void check_add_keysyms(void); extern int add_keysym(KeySym keysym); extern void delete_added_keycodes(int bequiet); extern void initialize_remap(char *infile); -extern int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new); +extern int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new_kc); extern void switch_to_xkb_if_better(void); extern char *short_kmbcf(char *str); extern void initialize_allowed_input(void); diff --git a/x11vnc/linuxfb.c b/x11vnc/linuxfb.c index f65a67d..1831c5f 100644 --- a/x11vnc/linuxfb.c +++ b/x11vnc/linuxfb.c @@ -265,6 +265,7 @@ char *console_guess(char *str, int *fd) { } else { sprintf(q, "map:%s@%s", file, atparms); } + free(atparms); return q; } diff --git a/x11vnc/macosx.c b/x11vnc/macosx.c index b3cff79..4b13528 100644 --- a/x11vnc/macosx.c +++ b/x11vnc/macosx.c @@ -241,6 +241,7 @@ char *macosx_console_guess(char *str, int *fd) { q = (char *) malloc(strlen("map:macosx:") + strlen(file) + 1 + strlen(atparms) + 1); sprintf(q, "map:macosx:%s@%s", file, atparms); + free(atparms); return q; } diff --git a/x11vnc/macosxCG.c b/x11vnc/macosxCG.c index 4f1fd0a..a465493 100644 --- a/x11vnc/macosxCG.c +++ b/x11vnc/macosxCG.c @@ -87,7 +87,9 @@ int dragum(void) { CGPoint loc; CGDirectDisplayID displayID2 = kCGDirectMainDisplay; +#ifdef X11VNC_MACOSX_USE_GETMAINDEVICE (void) GetMainDevice(); +#endif for (i=0; i< 50; i++) { usleep(1000*100); @@ -140,7 +142,9 @@ void macosxCG_init(void) { #endif displayID = kCGDirectMainDisplay; +#ifdef X11VNC_MACOSX_USE_GETMAINDEVICE (void) GetMainDevice(); +#endif CGSetLocalEventsSuppressionInterval(0.0); CGSetLocalEventsFilterDuringSupressionState( diff --git a/x11vnc/misc/Makefile.am b/x11vnc/misc/Makefile.am index 98a7511..e6a50aa 100644 --- a/x11vnc/misc/Makefile.am +++ b/x11vnc/misc/Makefile.am @@ -1,3 +1,3 @@ SUBDIRS = turbovnc DIST_SUBDIRS = turbovnc -EXTRA_DIST=README blockdpy.c dtVncPopup rx11vnc rx11vnc.pl shm_clear ranfb.pl slide.pl vcinject.pl x11vnc_loop Xdummy ultravnc_repeater.pl connect_switch panner.pl desktop.cgi inet6to4 +EXTRA_DIST=README blockdpy.c dtVncPopup rx11vnc rx11vnc.pl shm_clear ranfb.pl slide.pl vcinject.pl x11vnc_loop Xdummy ultravnc_repeater.pl connect_switch panner.pl desktop.cgi inet6to4 uinput.pl qt_tslib_inject.pl diff --git a/x11vnc/misc/README b/x11vnc/misc/README index f38616e..2ed1dff 100644 --- a/x11vnc/misc/README +++ b/x11vnc/misc/README @@ -26,6 +26,10 @@ x11vnc -pipeinput/-rawfb utilities: slide.pl amusing example using x11vnc -rawfb for jpeg slideshow. ranfb.pl example -rawfb setup:./ranfb.pl to set up a framebuffer. + uinput.pl test perl script for Linux uinput injection. + + qt_tslib_inject.pl touchscreen -pipeinput helper for tslib on qtmoko. + Misc. scripts: shm_clear list or remove orphaned shm slots from hard x11vnc crashes. diff --git a/x11vnc/misc/qt_tslib_inject.pl b/x11vnc/misc/qt_tslib_inject.pl new file mode 100755 index 0000000..d69d174 --- /dev/null +++ b/x11vnc/misc/qt_tslib_inject.pl @@ -0,0 +1,1064 @@ +#!/usr/bin/perl +# +# qt_tslib_inject.pl: +# +# touch screen input injection tool for use with x11vnc. +# +# example usage: +# +# x11vnc ... -rawfb console -pipeinput ./qt_tslib_inject_input.pl -env INJECT_OPTIONS=cal=/etc/pointercal +# +# See options below. +# +# tested on qtmoko (neo freerunner) with tslib. + +# +# Copyright (c) 2010 by Karl J. Runge +# +# qt_tslib_inject.pl 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. +# +# qt_tslib_inject.pl 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 qt_tslib_inject.pl; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +# or see . +# + +set_constants(); + +# one can set these env. vars. before running: + +# the device file to inject the events into: +# +$dev = $ENV{INJECT_DEV}; +$dev = "/dev/input/event1" unless $dev; + +# options, see below. useful: cal=/etc/pointercal +# +$options = $ENV{INJECT_OPTIONS}; +$options = '' unless $options ne ''; + +$debug = 0; # enable debugging output: +$pressure = 1; # level of touch pad pressure for click. +$btn_touch = 0; # send BTN_TOUCH on clicks instead of pressure changes. +$absalways = 0; # send a zero pressure absolute position event whenever mouse moves. +$dragskip = 0; # how often to skip injecting motion event while dragging. + +$a_xform = ''; # tslib's calibration coefficients. +@a = (); + +%keycmds = (); # user defined hotkeys to run external commands. + +# separate the options by comma, e.g. pressure=5,cal=/etc/pointercal + +if ($options =~ /absalways/i) { + # set to always send a zero pressure ABS event when mouse moves + $absalways = 1; +} +if ($options =~ /btn_touch/i) { + # send BTN_TOUCH on clicks. + $btn_touch = 1; +} +if ($options =~ /pressure=(\d+)/i) { + # level of touchpad pressure to use on a touch. + $pressure = $1; +} +if ($options =~ /dragskip=(\d+)/i) { + # when dragging with pressure, skip this many events. + $dragskip = $1; +} +if ($options =~ /cal=([^,]+)/i) { + # tslib's /etc/pointercal linear transform: + $a_xform = $1; + if (-f $a_xform) { + $a_xform = `head -n 1 '$a_xform'`; + chomp $a_xform; + $a_xform =~ s/^\s*//; + $a_xform =~ s/\s*$//; + } +} +if ($options =~ /keycmds=([^,]+)/i) { + # format: keysym1:command1+keysym2:command2+... + # e.g.: keycmds=F6:date+F7:'./x11vnc-0.9.10 -connect ./ctl.txt -R reset' + my $str = $1; + if (-f $str && open(F, "<$str")) { + $str = ''; + while () { + chomp; + $_ =~ s/^\s*//; + $_ =~ s/\s*$//; + next if /^#/; + next if $_ eq ""; + $str .= '+' if $str ne ''; + $str .= $_; + } + close F; + } + foreach my $part (split(/\+/, $str)) { + my ($key, $cmd) = split(/:/, $part, 2); + if ($key !~ /^\s*$/) { + $keycmds{$key} = $cmd; + } + } +} +if ($options =~ /debug=(\d+)/i) { + # debug printout + $debug = $1; +} elsif ($options =~ /debug/i) { + $debug = 1; +} + +# end of the top part that user should read and understand +# for setting options, etc. +###################################################################### + +$start = time(); + +# open the device for writing: +# +$modes = $O_WRONLY; +printf("open modes: 0x%x\n", $modes) if $debug; + +sysopen(FD, $dev, $modes) || die "$dev: $!"; + +my $curr_mask = 0; +my $curr_x = 0; +my $curr_y = 0; +my $down_count = 0; + +# read input events from x11vnc through STDIN: +# +while (<>) { + chomp; + if (/^Pointer/) { + my ($p, $client, $x, $y, $mask, $hint) = split(' ', $_, 6); + do_pointer($client, $x, $y, $mask, $hint); + } elsif (/^Keysym/) { + my ($k, $client, $down, $keysym, $name, $hint) = split(' ', $_, 6); + do_keysym($client, $down, $keysym, $name, $hint); + } +} + +close(FD); + +exit(0); + +sub do_keysym { + # qtmoko/neo does not support keystroke input. so these will be ignored. + # (one possibility would to be enable qtmoko to read from /dev/tty0. + # but the injection mechanism would need to be modified.) + my ($client, $down, $keysym, $name, $hint) = @_; + + $ENV{DO_KEYSYM} = "$client $down $keysym $name $hint"; + + # one could implement his own 'hot keys' here. + + # process any keycmds: + if (%keycmds && (exists $keycmds{$name} || exists $keycmds{ALL})) { + my $cmd = $keycmds{$name}; + if (!exists $keycmds{$name}) { + $cmd = $keycmds{ALL}; + print STDERR "keycmds: $name/ALL: running: $cmd\n"; + system("$cmd"); + } elsif ($down) { + print STDERR "keycmds: $name: running: $cmd\n"; + system("$cmd"); + } + return; + } + + $name = "XK_$name"; + my $nolookup = 0; + if (! exists $key_lookup{$name}) { + $nolookup = 1; + } elsif (! defined $key_lookup{$name}) { + $nolookup = 2; + } elsif ($key_lookup{$name} =~ /^\s*$/) { + $nolookup = 3; + } + if ($nolookup) { + print STDERR "do_keysym: key not implemented-$nolookup $down $keysym $name $hint.\n" if $debug; + return; + } + + print STDERR gettime() . " do_keysym: $name\n" if $debug; + do_key($key_lookup{$name}, $down); +} + +sub do_pointer { + my ($client, $x, $y, $mask, $hint) = @_; + my $x2 = $x; + my $y2 = $y; + if ($a_xform ne '') { + # this is tslib's /etc/pointercal format. + if (! @a) { + # -528 33408 -3417516 -44200 408 40292028 56541 + @a = split(' ', $a_xform); + foreach my $a (@a) { + $a += 0.0; + } + } + # this is the inverse of the tslib transformation: + # + $x2 = ( $a[4] * ($a[6] * $x - $a[2]) - $a[1] * ($a[6] * $y - $a[5]) ) + / ( $a[4] * $a[0] - $a[1] * $a[3]); + $y2 = ( $a[0] * ($a[6] * $y - $a[5]) - $a[3] * ($a[6] * $x - $a[2]) ) + / ( $a[4] * $a[0] - $a[1] * $a[3]); + $x2 = int($x2); + $y2 = int($y2); + } + + print STDERR gettime() . " do_pointer $x $y (=> $x2 $y2) $mask $hint.\n" if $debug; + + if (! $btn_touch) { + if ($curr_mask == 0 && $mask == 0) { + do_abs($x2, $y2, 0) if $absalways; + } elsif ($curr_mask == 0 && $mask != 0) { + do_abs($x2, $y2, $pressure); + $down_count = 0; + } elsif ($curr_mask != 0 && $mask == 0) { + do_abs($x2, $y2, 0); + } elsif ($curr_mask != 0 && $mask != 0) { + $down_count++; + if ($dragskip > 0) { + if ($down_count % $dragskip == 0) { + do_abs($x2, $y2, $pressure); + } else { + print STDERR "dragskip $down_count $dragskip\n" if $debug; + } + } else { + do_abs($x2, $y2, $pressure); + } + } + } else { + if ($curr_mask == 0 && $mask == 0) { + do_abs($x2, $y2, 0) if $absalways; + } elsif ($curr_mask == 0 && $mask != 0) { + do_abs($x2, $y2, 0); + do_btn($BTN_TOUCH, 1); + } elsif ($curr_mask != 0 && $mask == 0) { + do_abs($x2, $y2, 0); + do_btn($BTN_TOUCH, 0); + } elsif ($curr_mask != 0 && $mask != 0) { + ; + } + } + + $curr_mask = $mask; + $curr_x = $x2; + $curr_y = $y2; +} + +# struct input_event { +# struct timeval time; +# __u16 type; +# __u16 code; +# __s32 value; +# }; + +sub do_syn { + my $ev = gtod(); + $ev .= pack("S", $EV_SYN); + $ev .= pack("S", $SYN_REPORT); + $ev .= pack("i", 0); + print STDERR "do_syn EV_SYN\n" if $debug; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_syn: $!\n"; + } +} + +sub do_key { + # not supported by qtmoko + my ($key, $down) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_KEY); + $ev .= pack("S", $key); + $ev .= pack("i", $down); + print STDERR "do_key $key $down\n" if $debug; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_key: $!\n"; + } + do_syn(); +} + +sub do_btn { + # only BTN_TOUCH supported by qtmoko (but it seems to be ignored??) + my ($button, $down) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_KEY); + $ev .= pack("S", $button); + $ev .= pack("i", $down); + print STDERR "do_btn $button $down\n" if $debug; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_btn: $!\n"; + } + do_syn(); +} + +sub do_abs { + # absolute method is the workhorse for the touchscreen. + my ($x, $y, $p) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_Y); + $ev .= pack("i", $y); + print STDERR "do_abs y=$y\n" if $debug; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_X); + $ev .= pack("i", $x); + print STDERR "do_abs x=$x\n" if $debug; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_PRESSURE); + $ev .= pack("i", $p); + print STDERR "do_abs p=$p\n" if $debug; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + do_syn(); +} + +sub do_rel { + # not supported by qtmoko + my ($dx, $dy) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_REL); + $ev .= pack("S", $REL_Y); + $ev .= pack("i", $dy); + print STDERR "do_rel dy=$dy\n" if $debug; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_rel: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_REL); + $ev .= pack("S", $REL_X); + $ev .= pack("i", $dx); + print STDERR "do_rel dx=$dx\n"; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_rel: $!\n"; + } + do_syn(); +} + +sub gtod { + # 32 bit machines. TBD use perl module Time:HiRes. + $tv = ("\0" x 4) x 2; # assumes long is 4 bytes. should use pack. + $tz = ("\0" x 4) x 2; + syscall($linux_gettimeofday_syscall, $tv, $tz); + return $tv; +} + +sub gettime { + my $tv = gtod(); + my ($tv_sec, $tv_usec) = unpack("L2", $tv); + $tv_usec2 = sprintf("%8.6f", $tv_usec/1000000.0); + if ( $tv_usec2 =~ /^0\./ ) { + $tv_usec2 =~ s/^0\././; + $tv_sec = "$tv_sec$tv_usec2"; + } else { + $tv_sec = $tv_sec + ($tv_usec/1000000.0); + } + return sprintf("%.3f", $tv_sec - $start); +} + +sub fsleep { + my ($time) = @_; + select(undef, undef, undef, $time) if $time; +} + +sub set_constants { + +# from /usr/include/linux/uinput.h /usr/include/linux/input.h and x11vnc. + +# #define ABS_MAX 0x3f = 63 +# +# #define UINPUT_MAX_NAME_SIZE 80 +# +# struct input_id { +# __u16 bustype; +# __u16 vendor; +# __u16 product; +# __u16 version; +# }; +# +# struct uinput_user_dev { +# char name[UINPUT_MAX_NAME_SIZE]; +# struct input_id id; +# int ff_effects_max; +# int absmax[ABS_MAX + 1]; +# int absmin[ABS_MAX + 1]; +# int absfuzz[ABS_MAX + 1]; +# int absflat[ABS_MAX + 1]; +# }; +# #endif /* __UINPUT_H_ */ + +$EV_SYN = 0x00; +$EV_KEY = 0x01; +$EV_REL = 0x02; +$EV_ABS = 0x03; +$EV_MSC = 0x04; +$EV_SW = 0x05; +$EV_LED = 0x11; +$EV_SND = 0x12; +$EV_REP = 0x14; +$EV_FF = 0x15; +$EV_PWR = 0x16; +$EV_FF_STATUS = 0x17; +$EV_MAX = 0x1f; + +$ID_BUS = 0; +$ID_VENDOR = 1; +$ID_PRODUCT = 2; +$ID_VERSION = 3; + +$BUS_PCI = 0x01; +$BUS_ISAPNP = 0x02; +$BUS_USB = 0x03; +$BUS_HIL = 0x04; +$BUS_BLUETOOTH = 0x05; +$BUS_VIRTUAL = 0x06; + +$BUS_ISA = 0x10; +$BUS_I8042 = 0x11; +$BUS_XTKBD = 0x12; +$BUS_RS232 = 0x13; +$BUS_GAMEPORT = 0x14; +$BUS_PARPORT = 0x15; +$BUS_AMIGA = 0x16; +$BUS_ADB = 0x17; +$BUS_I2C = 0x18; +$BUS_HOST = 0x19; +$BUS_GSC = 0x1A; +$BUS_ATARI = 0x1B; + +$REL_X = 0x00; +$REL_Y = 0x01; +$REL_Z = 0x02; +$REL_RX = 0x03; +$REL_RY = 0x04; +$REL_RZ = 0x05; +$REL_HWHEEL = 0x06; +$REL_DIAL = 0x07; +$REL_WHEEL = 0x08; +$REL_MISC = 0x09; + +$ABS_X = 0x00; +$ABS_Y = 0x01; +$ABS_Z = 0x02; +$ABS_RX = 0x03; +$ABS_RY = 0x04; +$ABS_RZ = 0x05; +$ABS_THROTTLE = 0x06; +$ABS_RUDDER = 0x07; +$ABS_WHEEL = 0x08; +$ABS_GAS = 0x09; +$ABS_BRAKE = 0x0a; +$ABS_HAT0X = 0x10; +$ABS_HAT0Y = 0x11; +$ABS_HAT1X = 0x12; +$ABS_HAT1Y = 0x13; +$ABS_HAT2X = 0x14; +$ABS_HAT2Y = 0x15; +$ABS_HAT3X = 0x16; +$ABS_HAT3Y = 0x17; +$ABS_PRESSURE = 0x18; +$ABS_DISTANCE = 0x19; +$ABS_TILT_X = 0x1a; +$ABS_TILT_Y = 0x1b; +$ABS_TOOL_WIDTH = 0x1c; +$ABS_VOLUME = 0x20; +$ABS_MISC = 0x28; +$ABS_MT_TOUCH_MAJOR = 0x30; +$ABS_MT_TOUCH_MINOR = 0x31; +$ABS_MT_WIDTH_MAJOR = 0x32; +$ABS_MT_WIDTH_MINOR = 0x33; +$ABS_MT_ORIENTATION = 0x34; +$ABS_MT_POSITION_X = 0x35; +$ABS_MT_POSITION_Y = 0x36; +$ABS_MT_TOOL_TYPE = 0x37; +$ABS_MT_BLOB_ID = 0x38; +$ABS_MT_TRACKING_ID = 0x39; +#$ABS_MAX = 0x3f; + + +$BTN_MISC = 0x100; +$BTN_0 = 0x100; +$BTN_1 = 0x101; +$BTN_2 = 0x102; +$BTN_3 = 0x103; +$BTN_4 = 0x104; +$BTN_5 = 0x105; +$BTN_6 = 0x106; +$BTN_7 = 0x107; +$BTN_8 = 0x108; +$BTN_9 = 0x109; + +$BTN_MOUSE = 0x110; +$BTN_LEFT = 0x110; +$BTN_RIGHT = 0x111; +$BTN_MIDDLE = 0x112; +$BTN_SIDE = 0x113; +$BTN_EXTRA = 0x114; +$BTN_FORWARD = 0x115; +$BTN_BACK = 0x116; +$BTN_TASK = 0x117; + +$BTN_JOYSTICK = 0x120; +$BTN_TRIGGER = 0x120; +$BTN_THUMB = 0x121; +$BTN_THUMB2 = 0x122; +$BTN_TOP = 0x123; +$BTN_TOP2 = 0x124; +$BTN_PINKIE = 0x125; +$BTN_BASE = 0x126; +$BTN_BASE2 = 0x127; +$BTN_BASE3 = 0x128; +$BTN_BASE4 = 0x129; +$BTN_BASE5 = 0x12a; +$BTN_BASE6 = 0x12b; +$BTN_DEAD = 0x12f; + +$BTN_GAMEPAD = 0x130; +$BTN_A = 0x130; +$BTN_B = 0x131; +$BTN_C = 0x132; +$BTN_X = 0x133; +$BTN_Y = 0x134; +$BTN_Z = 0x135; +$BTN_TL = 0x136; +$BTN_TR = 0x137; +$BTN_TL2 = 0x138; +$BTN_TR2 = 0x139; +$BTN_SELECT = 0x13a; +$BTN_START = 0x13b; +$BTN_MODE = 0x13c; +$BTN_THUMBL = 0x13d; +$BTN_THUMBR = 0x13e; + +$BTN_DIGI = 0x140; +$BTN_TOOL_PEN = 0x140; +$BTN_TOOL_RUBBER = 0x141; +$BTN_TOOL_BRUSH = 0x142; +$BTN_TOOL_PENCIL = 0x143; +$BTN_TOOL_AIRBRUSH = 0x144; +$BTN_TOOL_FINGER = 0x145; +$BTN_TOOL_MOUSE = 0x146; +$BTN_TOOL_LENS = 0x147; +$BTN_TOUCH = 0x14a; +$BTN_STYLUS = 0x14b; +$BTN_STYLUS2 = 0x14c; +$BTN_TOOL_DOUBLETAP = 0x14d; +$BTN_TOOL_TRIPLETAP = 0x14e; + +$BTN_WHEEL = 0x150; +$BTN_GEAR_DOWN = 0x150; +$BTN_GEAR_UP = 0x151; + +$SYN_REPORT = 0; +$SYN_CONFIG = 1; +$SYN_MT_REPORT = 2; + +$KEY_RESERVED = 0; +$KEY_ESC = 1; +$KEY_1 = 2; +$KEY_2 = 3; +$KEY_3 = 4; +$KEY_4 = 5; +$KEY_5 = 6; +$KEY_6 = 7; +$KEY_7 = 8; +$KEY_8 = 9; +$KEY_9 = 10; +$KEY_0 = 11; +$KEY_MINUS = 12; +$KEY_EQUAL = 13; +$KEY_BACKSPACE = 14; +$KEY_TAB = 15; +$KEY_Q = 16; +$KEY_W = 17; +$KEY_E = 18; +$KEY_R = 19; +$KEY_T = 20; +$KEY_Y = 21; +$KEY_U = 22; +$KEY_I = 23; +$KEY_O = 24; +$KEY_P = 25; +$KEY_LEFTBRACE = 26; +$KEY_RIGHTBRACE = 27; +$KEY_ENTER = 28; +$KEY_LEFTCTRL = 29; +$KEY_A = 30; +$KEY_S = 31; +$KEY_D = 32; +$KEY_F = 33; +$KEY_G = 34; +$KEY_H = 35; +$KEY_J = 36; +$KEY_K = 37; +$KEY_L = 38; +$KEY_SEMICOLON = 39; +$KEY_APOSTROPHE = 40; +$KEY_GRAVE = 41; +$KEY_LEFTSHIFT = 42; +$KEY_BACKSLASH = 43; +$KEY_Z = 44; +$KEY_X = 45; +$KEY_C = 46; +$KEY_V = 47; +$KEY_B = 48; +$KEY_N = 49; +$KEY_M = 50; +$KEY_COMMA = 51; +$KEY_DOT = 52; +$KEY_SLASH = 53; +$KEY_RIGHTSHIFT = 54; +$KEY_KPASTERISK = 55; +$KEY_LEFTALT = 56; +$KEY_SPACE = 57; +$KEY_CAPSLOCK = 58; +$KEY_F1 = 59; +$KEY_F2 = 60; +$KEY_F3 = 61; +$KEY_F4 = 62; +$KEY_F5 = 63; +$KEY_F6 = 64; +$KEY_F7 = 65; +$KEY_F8 = 66; +$KEY_F9 = 67; +$KEY_F10 = 68; +$KEY_NUMLOCK = 69; +$KEY_SCROLLLOCK = 70; +$KEY_KP7 = 71; +$KEY_KP8 = 72; +$KEY_KP9 = 73; +$KEY_KPMINUS = 74; +$KEY_KP4 = 75; +$KEY_KP5 = 76; +$KEY_KP6 = 77; +$KEY_KPPLUS = 78; +$KEY_KP1 = 79; +$KEY_KP2 = 80; +$KEY_KP3 = 81; +$KEY_KP0 = 82; +$KEY_KPDOT = 83; +$KEY_103RD = 84; +$KEY_F13 = 85; +$KEY_102ND = 86; +$KEY_F11 = 87; +$KEY_F12 = 88; +$KEY_F14 = 89; +$KEY_F15 = 90; +$KEY_F16 = 91; +$KEY_F17 = 92; +$KEY_F18 = 93; +$KEY_F19 = 94; +$KEY_F20 = 95; +$KEY_KPENTER = 96; +$KEY_RIGHTCTRL = 97; +$KEY_KPSLASH = 98; +$KEY_SYSRQ = 99; +$KEY_RIGHTALT = 100; +$KEY_LINEFEED = 101; +$KEY_HOME = 102; +$KEY_UP = 103; +$KEY_PAGEUP = 104; +$KEY_LEFT = 105; +$KEY_RIGHT = 106; +$KEY_END = 107; +$KEY_DOWN = 108; +$KEY_PAGEDOWN = 109; +$KEY_INSERT = 110; +$KEY_DELETE = 111; +$KEY_MACRO = 112; +$KEY_MUTE = 113; +$KEY_VOLUMEDOWN = 114; +$KEY_VOLUMEUP = 115; +$KEY_POWER = 116; +$KEY_KPEQUAL = 117; +$KEY_KPPLUSMINUS = 118; +$KEY_PAUSE = 119; +$KEY_F21 = 120; +$KEY_F22 = 121; +$KEY_F23 = 122; +$KEY_F24 = 123; +$KEY_KPCOMMA = 124; +$KEY_LEFTMETA = 125; +$KEY_RIGHTMETA = 126; +$KEY_COMPOSE = 127; +$KEY_STOP = 128; +$KEY_AGAIN = 129; +$KEY_PROPS = 130; +$KEY_UNDO = 131; +$KEY_FRONT = 132; +$KEY_COPY = 133; +$KEY_OPEN = 134; +$KEY_PASTE = 135; +$KEY_FIND = 136; +$KEY_CUT = 137; +$KEY_HELP = 138; +$KEY_MENU = 139; +$KEY_CALC = 140; +$KEY_SETUP = 141; +$KEY_SLEEP = 142; +$KEY_WAKEUP = 143; +$KEY_FILE = 144; +$KEY_SENDFILE = 145; +$KEY_DELETEFILE = 146; +$KEY_XFER = 147; +$KEY_PROG1 = 148; +$KEY_PROG2 = 149; +$KEY_WWW = 150; +$KEY_MSDOS = 151; +$KEY_COFFEE = 152; +$KEY_DIRECTION = 153; +$KEY_CYCLEWINDOWS = 154; +$KEY_MAIL = 155; +$KEY_BOOKMARKS = 156; +$KEY_COMPUTER = 157; +$KEY_BACK = 158; +$KEY_FORWARD = 159; +$KEY_CLOSECD = 160; +$KEY_EJECTCD = 161; +$KEY_EJECTCLOSECD = 162; +$KEY_NEXTSONG = 163; +$KEY_PLAYPAUSE = 164; +$KEY_PREVIOUSSONG = 165; +$KEY_STOPCD = 166; +$KEY_RECORD = 167; +$KEY_REWIND = 168; +$KEY_PHONE = 169; +$KEY_ISO = 170; +$KEY_CONFIG = 171; +$KEY_HOMEPAGE = 172; +$KEY_REFRESH = 173; +$KEY_EXIT = 174; +$KEY_MOVE = 175; +$KEY_EDIT = 176; +$KEY_SCROLLUP = 177; +$KEY_SCROLLDOWN = 178; +$KEY_KPLEFTPAREN = 179; +$KEY_KPRIGHTPAREN = 180; +$KEY_INTL1 = 181; +$KEY_INTL2 = 182; +$KEY_INTL3 = 183; +$KEY_INTL4 = 184; +$KEY_INTL5 = 185; +$KEY_INTL6 = 186; +$KEY_INTL7 = 187; +$KEY_INTL8 = 188; +$KEY_INTL9 = 189; +$KEY_LANG1 = 190; +$KEY_LANG2 = 191; +$KEY_LANG3 = 192; +$KEY_LANG4 = 193; +$KEY_LANG5 = 194; +$KEY_LANG6 = 195; +$KEY_LANG7 = 196; +$KEY_LANG8 = 197; +$KEY_LANG9 = 198; +$KEY_PLAYCD = 200; +$KEY_PAUSECD = 201; +$KEY_PROG3 = 202; +$KEY_PROG4 = 203; +$KEY_SUSPEND = 205; +$KEY_CLOSE = 206; +$KEY_PLAY = 207; +$KEY_FASTFORWARD = 208; +$KEY_BASSBOOST = 209; +$KEY_PRINT = 210; +$KEY_HP = 211; +$KEY_CAMERA = 212; +$KEY_SOUND = 213; +$KEY_QUESTION = 214; +$KEY_EMAIL = 215; +$KEY_CHAT = 216; +$KEY_SEARCH = 217; +$KEY_CONNECT = 218; +$KEY_FINANCE = 219; +$KEY_SPORT = 220; +$KEY_SHOP = 221; +$KEY_ALTERASE = 222; +$KEY_CANCEL = 223; +$KEY_BRIGHTNESSDOWN = 224; +$KEY_BRIGHTNESSUP = 225; +$KEY_MEDIA = 226; +$KEY_UNKNOWN = 240; +$KEY_OK = 0x160; +$KEY_SELECT = 0x161; +$KEY_GOTO = 0x162; +$KEY_CLEAR = 0x163; +$KEY_POWER2 = 0x164; +$KEY_OPTION = 0x165; +$KEY_INFO = 0x166; +$KEY_TIME = 0x167; +$KEY_VENDOR = 0x168; +$KEY_ARCHIVE = 0x169; +$KEY_PROGRAM = 0x16a; +$KEY_CHANNEL = 0x16b; +$KEY_FAVORITES = 0x16c; +$KEY_EPG = 0x16d; +$KEY_PVR = 0x16e; +$KEY_MHP = 0x16f; +$KEY_LANGUAGE = 0x170; +$KEY_TITLE = 0x171; +$KEY_SUBTITLE = 0x172; +$KEY_ANGLE = 0x173; +$KEY_ZOOM = 0x174; +$KEY_MODE = 0x175; +$KEY_KEYBOARD = 0x176; +$KEY_SCREEN = 0x177; +$KEY_PC = 0x178; +$KEY_TV = 0x179; +$KEY_TV2 = 0x17a; +$KEY_VCR = 0x17b; +$KEY_VCR2 = 0x17c; +$KEY_SAT = 0x17d; +$KEY_SAT2 = 0x17e; +$KEY_CD = 0x17f; +$KEY_TAPE = 0x180; +$KEY_RADIO = 0x181; +$KEY_TUNER = 0x182; +$KEY_PLAYER = 0x183; +$KEY_TEXT = 0x184; +$KEY_DVD = 0x185; +$KEY_AUX = 0x186; +$KEY_MP3 = 0x187; +$KEY_AUDIO = 0x188; +$KEY_VIDEO = 0x189; +$KEY_DIRECTORY = 0x18a; +$KEY_LIST = 0x18b; +$KEY_MEMO = 0x18c; +$KEY_CALENDAR = 0x18d; +$KEY_RED = 0x18e; +$KEY_GREEN = 0x18f; +$KEY_YELLOW = 0x190; +$KEY_BLUE = 0x191; +$KEY_CHANNELUP = 0x192; +$KEY_CHANNELDOWN = 0x193; +$KEY_FIRST = 0x194; +$KEY_LAST = 0x195; +$KEY_AB = 0x196; +$KEY_NEXT = 0x197; +$KEY_RESTART = 0x198; +$KEY_SLOW = 0x199; +$KEY_SHUFFLE = 0x19a; +$KEY_BREAK = 0x19b; +$KEY_PREVIOUS = 0x19c; +$KEY_DIGITS = 0x19d; +$KEY_TEEN = 0x19e; +$KEY_TWEN = 0x19f; +$KEY_DEL_EOL = 0x1c0; +$KEY_DEL_EOS = 0x1c1; +$KEY_INS_LINE = 0x1c2; +$KEY_DEL_LINE = 0x1c3; +$KEY_MAX = 0x1ff; + + + $key_lookup{XK_Escape} = $KEY_ESC; + $key_lookup{XK_1} = $KEY_1; + $key_lookup{XK_2} = $KEY_2; + $key_lookup{XK_3} = $KEY_3; + $key_lookup{XK_4} = $KEY_4; + $key_lookup{XK_5} = $KEY_5; + $key_lookup{XK_6} = $KEY_6; + $key_lookup{XK_7} = $KEY_7; + $key_lookup{XK_8} = $KEY_8; + $key_lookup{XK_9} = $KEY_9; + $key_lookup{XK_0} = $KEY_0; + $key_lookup{XK_exclam} = $KEY_1; + $key_lookup{XK_at} = $KEY_2; + $key_lookup{XK_numbersign} = $KEY_3; + $key_lookup{XK_dollar} = $KEY_4; + $key_lookup{XK_percent} = $KEY_5; + $key_lookup{XK_asciicircum} = $KEY_6; + $key_lookup{XK_ampersand} = $KEY_7; + $key_lookup{XK_asterisk} = $KEY_8; + $key_lookup{XK_parenleft} = $KEY_9; + $key_lookup{XK_parenright} = $KEY_0; + $key_lookup{XK_minus} = $KEY_MINUS; + $key_lookup{XK_underscore} = $KEY_MINUS; + $key_lookup{XK_equal} = $KEY_EQUAL; + $key_lookup{XK_plus} = $KEY_EQUAL; + $key_lookup{XK_BackSpace} = $KEY_BACKSPACE; + $key_lookup{XK_Tab} = $KEY_TAB; + $key_lookup{XK_q} = $KEY_Q; + $key_lookup{XK_Q} = $KEY_Q; + $key_lookup{XK_w} = $KEY_W; + $key_lookup{XK_W} = $KEY_W; + $key_lookup{XK_e} = $KEY_E; + $key_lookup{XK_E} = $KEY_E; + $key_lookup{XK_r} = $KEY_R; + $key_lookup{XK_R} = $KEY_R; + $key_lookup{XK_t} = $KEY_T; + $key_lookup{XK_T} = $KEY_T; + $key_lookup{XK_y} = $KEY_Y; + $key_lookup{XK_Y} = $KEY_Y; + $key_lookup{XK_u} = $KEY_U; + $key_lookup{XK_U} = $KEY_U; + $key_lookup{XK_i} = $KEY_I; + $key_lookup{XK_I} = $KEY_I; + $key_lookup{XK_o} = $KEY_O; + $key_lookup{XK_O} = $KEY_O; + $key_lookup{XK_p} = $KEY_P; + $key_lookup{XK_P} = $KEY_P; + $key_lookup{XK_braceleft} = $KEY_LEFTBRACE; + $key_lookup{XK_braceright} = $KEY_RIGHTBRACE; + $key_lookup{XK_bracketleft} = $KEY_LEFTBRACE; + $key_lookup{XK_bracketright} = $KEY_RIGHTBRACE; + $key_lookup{XK_Return} = $KEY_ENTER; + $key_lookup{XK_Control_L} = $KEY_LEFTCTRL; + $key_lookup{XK_a} = $KEY_A; + $key_lookup{XK_A} = $KEY_A; + $key_lookup{XK_s} = $KEY_S; + $key_lookup{XK_S} = $KEY_S; + $key_lookup{XK_d} = $KEY_D; + $key_lookup{XK_D} = $KEY_D; + $key_lookup{XK_f} = $KEY_F; + $key_lookup{XK_F} = $KEY_F; + $key_lookup{XK_g} = $KEY_G; + $key_lookup{XK_G} = $KEY_G; + $key_lookup{XK_h} = $KEY_H; + $key_lookup{XK_H} = $KEY_H; + $key_lookup{XK_j} = $KEY_J; + $key_lookup{XK_J} = $KEY_J; + $key_lookup{XK_k} = $KEY_K; + $key_lookup{XK_K} = $KEY_K; + $key_lookup{XK_l} = $KEY_L; + $key_lookup{XK_L} = $KEY_L; + $key_lookup{XK_semicolon} = $KEY_SEMICOLON; + $key_lookup{XK_colon} = $KEY_SEMICOLON; + $key_lookup{XK_apostrophe} = $KEY_APOSTROPHE; + $key_lookup{XK_quotedbl} = $KEY_APOSTROPHE; + $key_lookup{XK_grave} = $KEY_GRAVE; + $key_lookup{XK_asciitilde} = $KEY_GRAVE; + $key_lookup{XK_Shift_L} = $KEY_LEFTSHIFT; + $key_lookup{XK_backslash} = $KEY_BACKSLASH; + $key_lookup{XK_bar} = $KEY_BACKSLASH; + $key_lookup{XK_z} = $KEY_Z; + $key_lookup{XK_Z} = $KEY_Z; + $key_lookup{XK_x} = $KEY_X; + $key_lookup{XK_X} = $KEY_X; + $key_lookup{XK_c} = $KEY_C; + $key_lookup{XK_C} = $KEY_C; + $key_lookup{XK_v} = $KEY_V; + $key_lookup{XK_V} = $KEY_V; + $key_lookup{XK_b} = $KEY_B; + $key_lookup{XK_B} = $KEY_B; + $key_lookup{XK_n} = $KEY_N; + $key_lookup{XK_N} = $KEY_N; + $key_lookup{XK_m} = $KEY_M; + $key_lookup{XK_M} = $KEY_M; + $key_lookup{XK_comma} = $KEY_COMMA; + $key_lookup{XK_less} = $KEY_COMMA; + $key_lookup{XK_period} = $KEY_DOT; + $key_lookup{XK_greater} = $KEY_DOT; + $key_lookup{XK_slash} = $KEY_SLASH; + $key_lookup{XK_question} = $KEY_SLASH; + $key_lookup{XK_Shift_R} = $KEY_RIGHTSHIFT; + $key_lookup{XK_KP_Multiply} = $KEY_KPASTERISK; + $key_lookup{XK_Alt_L} = $KEY_LEFTALT; + $key_lookup{XK_space} = $KEY_SPACE; + $key_lookup{XK_Caps_Lock} = $KEY_CAPSLOCK; + $key_lookup{XK_F1} = $KEY_F1; + $key_lookup{XK_F2} = $KEY_F2; + $key_lookup{XK_F3} = $KEY_F3; + $key_lookup{XK_F4} = $KEY_F4; + $key_lookup{XK_F5} = $KEY_F5; + $key_lookup{XK_F6} = $KEY_F6; + $key_lookup{XK_F7} = $KEY_F7; + $key_lookup{XK_F8} = $KEY_F8; + $key_lookup{XK_F9} = $KEY_F9; + $key_lookup{XK_F10} = $KEY_F10; + $key_lookup{XK_Num_Lock} = $KEY_NUMLOCK; + $key_lookup{XK_Scroll_Lock} = $KEY_SCROLLLOCK; + $key_lookup{XK_KP_7} = $KEY_KP7; + $key_lookup{XK_KP_8} = $KEY_KP8; + $key_lookup{XK_KP_9} = $KEY_KP9; + $key_lookup{XK_KP_Subtract} = $KEY_KPMINUS; + $key_lookup{XK_KP_4} = $KEY_KP4; + $key_lookup{XK_KP_5} = $KEY_KP5; + $key_lookup{XK_KP_6} = $KEY_KP6; + $key_lookup{XK_KP_Add} = $KEY_KPPLUS; + $key_lookup{XK_KP_1} = $KEY_KP1; + $key_lookup{XK_KP_2} = $KEY_KP2; + $key_lookup{XK_KP_3} = $KEY_KP3; + $key_lookup{XK_KP_0} = $KEY_KP0; + $key_lookup{XK_KP_Decimal} = $KEY_KPDOT; + $key_lookup{XK_F13} = $KEY_F13; + $key_lookup{XK_F11} = $KEY_F11; + $key_lookup{XK_F12} = $KEY_F12; + $key_lookup{XK_F14} = $KEY_F14; + $key_lookup{XK_F15} = $KEY_F15; + $key_lookup{XK_F16} = $KEY_F16; + $key_lookup{XK_F17} = $KEY_F17; + $key_lookup{XK_F18} = $KEY_F18; + $key_lookup{XK_F19} = $KEY_F19; + $key_lookup{XK_F20} = $KEY_F20; + $key_lookup{XK_KP_Enter} = $KEY_KPENTER; + $key_lookup{XK_Control_R} = $KEY_RIGHTCTRL; + $key_lookup{XK_KP_Divide} = $KEY_KPSLASH; + $key_lookup{XK_Sys_Req} = $KEY_SYSRQ; + $key_lookup{XK_Alt_R} = $KEY_RIGHTALT; + $key_lookup{XK_Linefeed} = $KEY_LINEFEED; + $key_lookup{XK_Home} = $KEY_HOME; + $key_lookup{XK_Up} = $KEY_UP; + $key_lookup{XK_Page_Up} = $KEY_PAGEUP; + $key_lookup{XK_Left} = $KEY_LEFT; + $key_lookup{XK_Right} = $KEY_RIGHT; + $key_lookup{XK_End} = $KEY_END; + $key_lookup{XK_Down} = $KEY_DOWN; + $key_lookup{XK_Page_Down} = $KEY_PAGEDOWN; + $key_lookup{XK_Insert} = $KEY_INSERT; + $key_lookup{XK_Delete} = $KEY_DELETE; + $key_lookup{XK_KP_Equal} = $KEY_KPEQUAL; + $key_lookup{XK_Pause} = $KEY_PAUSE; + $key_lookup{XK_F21} = $KEY_F21; + $key_lookup{XK_F22} = $KEY_F22; + $key_lookup{XK_F23} = $KEY_F23; + $key_lookup{XK_F24} = $KEY_F24; + $key_lookup{XK_KP_Separator} = $KEY_KPCOMMA; + $key_lookup{XK_Meta_L} = $KEY_LEFTMETA; + $key_lookup{XK_Meta_R} = $KEY_RIGHTMETA; + $key_lookup{XK_Multi_key} = $KEY_COMPOSE; + +$ABS_MAX = 63; + +$UI_DEV_CREATE = 0x5501; +$UI_DEV_DESTROY = 0x5502; +$UI_SET_EVBIT = 0x40045564; +$UI_SET_KEYBIT = 0x40045565; +$UI_SET_RELBIT = 0x40045566; +$UI_SET_ABSBIT = 0x40045567; + +# FIXME: time hires, etc. +$linux_gettimeofday_syscall = 78; + +$O_RDONLY = 00; +$O_WRONLY = 01; +$O_RDWR = 02; +$O_NDELAY = 04000; + +} diff --git a/x11vnc/misc/uinput.pl b/x11vnc/misc/uinput.pl new file mode 100755 index 0000000..9620140 --- /dev/null +++ b/x11vnc/misc/uinput.pl @@ -0,0 +1,946 @@ +#!/usr/bin/perl + +# This is a test injection script for Linux uinput. +# It can be handy working out / troubleshooting Linux uinput injection on a new device. + +# +# Copyright (c) 2010 by Karl J. Runge +# +# uinput.pl 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. +# +# uinput.pl 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 uinput.pl; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +# or see . +# + +set_constants(); + +# options for what injection to handle: +$rel = 1; +$abs = 1; +$touch = 1; +$allkeys = 1; + +# these can be set via env: + +$WIDTH = $ENV{WIDTH}; +$WIDTH = 480 unless $WIDTH; +$HEIGHT = $ENV{HEIGHT}; +$HEIGHT = 640 unless $HEIGHT; +$DEV = $ENV{DEV}; +$DEV = "/dev/input/uinput" unless $DEV; + +# this fills in name and input type part of uinput_user_dev struct: + +$udev = "uinput.pl"; +$n = 80 - length($udev); +$udev .= "\0" x $n; + +$udev .= "\0" x 2; # bus +$udev .= "\0" x 2; # vendor +$udev .= "\0" x 2; # product +$udev .= "\0" x 2; # version + +$udev .= "\0" x 4; # ff_effects_max + +# this fills in the abs arrays: +# +foreach $type (qw(absmax absmin absfuzz absflat)) { + $n = $ABS_MAX + 1; + for ($j = 0; $j < $n; $j++) { + if ($abs && $type eq 'absmax' && $j == $ABS_X) { + $udev .= pack("i", $WIDTH-1); + } elsif ($abs && $type eq 'absmax' && $j == $ABS_Y) { + $udev .= pack("i", $HEIGHT-1); + } else { + $udev .= "\0" x 4; + } + } +} + +print "udev: ", length($udev) . " '$udev'\n"; + +$modes = $O_RDWR; +$modes = $O_WRONLY | $O_NDELAY; +printf("open modes: 0x%x\n", $modes); + +sysopen(FD, $DEV, $modes) || die "$DEV: $!"; + +if ($rel) { + io_ctl($UI_SET_EVBIT, $EV_REL); + io_ctl($UI_SET_RELBIT, $REL_X); + io_ctl($UI_SET_RELBIT, $REL_Y); +} + +io_ctl($UI_SET_EVBIT, $EV_KEY); + +io_ctl($UI_SET_EVBIT, $EV_SYN); + +for ($i=0; $i < 256; $i++) { + last unless $allkeys; + io_ctl($UI_SET_KEYBIT, $i); +} + +io_ctl($UI_SET_KEYBIT, $BTN_MOUSE); +io_ctl($UI_SET_KEYBIT, $BTN_LEFT); +io_ctl($UI_SET_KEYBIT, $BTN_MIDDLE); +io_ctl($UI_SET_KEYBIT, $BTN_RIGHT); +io_ctl($UI_SET_KEYBIT, $BTN_FORWARD); +io_ctl($UI_SET_KEYBIT, $BTN_BACK); + +if ($abs) { + io_ctl($UI_SET_KEYBIT, $BTN_TOUCH) if $touch; + io_ctl($UI_SET_EVBIT, $EV_ABS); + io_ctl($UI_SET_ABSBIT, $ABS_X); + io_ctl($UI_SET_ABSBIT, $ABS_Y); +} + +$ret = syswrite(FD, $udev, length($udev)); +print "syswrite: $ret\n"; + +io_ctl($UI_DEV_CREATE); +fsleep(0.25); + +# this should show our new virtual device: +# +system("cat /proc/bus/input/devices 1>&2"); +print STDERR "\n"; + +################################################# +# put in your various test injection events here: + +#do_key($KEY_A, 1, 0.1); +#do_key($KEY_A, 0, 0.1); + +#do_key($KEY_POWER, 1, 0.1); +#do_key($KEY_POWER, 0, 0.1); + +do_abs(118, 452, 0, 0.1); + +do_abs(110, 572, 1, 0.1); + +do_btn($BTN_TOUCH, 1, 0.1); +do_btn($BTN_TOUCH, 0, 0.1); + +do_btn($BTN_MOUSE, 1, 0.1); +do_btn($BTN_MOUSE, 0, 0.1); +################################################# + +fsleep(0.25); +io_ctl($UI_DEV_DESTROY); + +close(FD); + +exit(0); + +sub io_ctl { + my ($cmd, $val) = @_; + if (defined $val) { + my $ret = syscall($linux_ioctl_syscall, fileno(FD), $cmd, $val); + my $err = $!; $err = '' if $ret == 0; + print STDERR "io_ctl(FD, $cmd, $val) = $ret $err\n"; + } else { + my $ret = syscall($linux_ioctl_syscall, fileno(FD), $cmd); + my $err = $!; $err = '' if $ret == 0; + print STDERR "io_ctl(FD, $cmd) = $ret $err\n"; + } +} + +sub do_syn { + my $ev = gtod(); + $ev .= pack("S", $EV_SYN); + $ev .= pack("S", $SYN_REPORT); + $ev .= pack("i", 0); + print STDERR "do_syn EV_SYN\n"; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_syn: $!\n"; + } +} + +sub do_key { + my ($key, $down, $sleep) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_KEY); + $ev .= pack("S", $key); + $ev .= pack("i", $down); + print STDERR "do_key $key $down\n"; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_key: $!\n"; + } + do_syn(); + fsleep($sleep); + print STDERR "\n"; +} + +sub do_btn { + my ($button, $down, $sleep) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_KEY); + $ev .= pack("S", $button); + $ev .= pack("i", $down); + print STDERR "do_btn $button $down\n"; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_btn: $!\n"; + } + do_syn(); + fsleep($sleep); + print STDERR "\n"; +} + +sub do_abs { + my ($x, $y, $p, $sleep) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_Y); + $ev .= pack("i", $y); + print STDERR "do_abs y=$y\n"; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_X); + $ev .= pack("i", $x); + print STDERR "do_abs x=$x\n"; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_ABS); + $ev .= pack("S", $ABS_PRESSURE); + $ev .= pack("i", $p); + print STDERR "do_abs p=$p\n"; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_abs: $!\n"; + } + do_syn(); + fsleep($sleep); + print STDERR "\n"; +} + +sub do_rel { + my ($dx, $dy, $sleep) = @_; + my $ev = gtod(); + $ev .= pack("S", $EV_REL); + $ev .= pack("S", $REL_Y); + $ev .= pack("i", $dy); + print STDERR "do_rel dy=$dy\n"; + my $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_rel: $!\n"; + } + $ev = gtod(); + $ev .= pack("S", $EV_REL); + $ev .= pack("S", $REL_X); + $ev .= pack("i", $dx); + print STDERR "do_rel dx=$dx\n"; + $ret = syswrite(FD, $ev, length($ev)); + if (!defined $ret) { + print STDERR "do_rel: $!\n"; + } + do_syn(); + fsleep($sleep); + print STDERR "\n"; +} + +sub gtod { + $tv = ("\0" x 4) x 2; # assumes long is 4 bytes. FIXME: use pack. + $tz = ("\0" x 4) x 2; + syscall($linux_gettimeofday_syscall, $tv, $tz); + return $tv; +} + +sub fsleep { + my ($time) = @_; + select(undef, undef, undef, $time) if $time; +} + +sub set_constants { + +# from /usr/include/linux/uinput.h /usr/include/linux/input.h and x11vnc. + +# #define ABS_MAX 0x3f = 63 +# +# #define UINPUT_MAX_NAME_SIZE 80 +# +# struct input_id { +# __u16 bustype; +# __u16 vendor; +# __u16 product; +# __u16 version; +# }; +# +# struct uinput_user_dev { +# char name[UINPUT_MAX_NAME_SIZE]; +# struct input_id id; +# int ff_effects_max; +# int absmax[ABS_MAX + 1]; +# int absmin[ABS_MAX + 1]; +# int absfuzz[ABS_MAX + 1]; +# int absflat[ABS_MAX + 1]; +# }; +# #endif /* __UINPUT_H_ */ + +$EV_SYN = 0x00; +$EV_KEY = 0x01; +$EV_REL = 0x02; +$EV_ABS = 0x03; +$EV_MSC = 0x04; +$EV_SW = 0x05; +$EV_LED = 0x11; +$EV_SND = 0x12; +$EV_REP = 0x14; +$EV_FF = 0x15; +$EV_PWR = 0x16; +$EV_FF_STATUS = 0x17; +$EV_MAX = 0x1f; + +$ID_BUS = 0; +$ID_VENDOR = 1; +$ID_PRODUCT = 2; +$ID_VERSION = 3; + +$BUS_PCI = 0x01; +$BUS_ISAPNP = 0x02; +$BUS_USB = 0x03; +$BUS_HIL = 0x04; +$BUS_BLUETOOTH = 0x05; +$BUS_VIRTUAL = 0x06; + +$BUS_ISA = 0x10; +$BUS_I8042 = 0x11; +$BUS_XTKBD = 0x12; +$BUS_RS232 = 0x13; +$BUS_GAMEPORT = 0x14; +$BUS_PARPORT = 0x15; +$BUS_AMIGA = 0x16; +$BUS_ADB = 0x17; +$BUS_I2C = 0x18; +$BUS_HOST = 0x19; +$BUS_GSC = 0x1A; +$BUS_ATARI = 0x1B; + +$REL_X = 0x00; +$REL_Y = 0x01; +$REL_Z = 0x02; +$REL_RX = 0x03; +$REL_RY = 0x04; +$REL_RZ = 0x05; +$REL_HWHEEL = 0x06; +$REL_DIAL = 0x07; +$REL_WHEEL = 0x08; +$REL_MISC = 0x09; + +$ABS_X = 0x00; +$ABS_Y = 0x01; +$ABS_Z = 0x02; +$ABS_RX = 0x03; +$ABS_RY = 0x04; +$ABS_RZ = 0x05; +$ABS_THROTTLE = 0x06; +$ABS_RUDDER = 0x07; +$ABS_WHEEL = 0x08; +$ABS_GAS = 0x09; +$ABS_BRAKE = 0x0a; +$ABS_HAT0X = 0x10; +$ABS_HAT0Y = 0x11; +$ABS_HAT1X = 0x12; +$ABS_HAT1Y = 0x13; +$ABS_HAT2X = 0x14; +$ABS_HAT2Y = 0x15; +$ABS_HAT3X = 0x16; +$ABS_HAT3Y = 0x17; +$ABS_PRESSURE = 0x18; +$ABS_DISTANCE = 0x19; +$ABS_TILT_X = 0x1a; +$ABS_TILT_Y = 0x1b; +$ABS_TOOL_WIDTH = 0x1c; +$ABS_VOLUME = 0x20; +$ABS_MISC = 0x28; +$ABS_MT_TOUCH_MAJOR = 0x30; +$ABS_MT_TOUCH_MINOR = 0x31; +$ABS_MT_WIDTH_MAJOR = 0x32; +$ABS_MT_WIDTH_MINOR = 0x33; +$ABS_MT_ORIENTATION = 0x34; +$ABS_MT_POSITION_X = 0x35; +$ABS_MT_POSITION_Y = 0x36; +$ABS_MT_TOOL_TYPE = 0x37; +$ABS_MT_BLOB_ID = 0x38; +$ABS_MT_TRACKING_ID = 0x39; +#$ABS_MAX = 0x3f; + + +$BTN_MISC = 0x100; +$BTN_0 = 0x100; +$BTN_1 = 0x101; +$BTN_2 = 0x102; +$BTN_3 = 0x103; +$BTN_4 = 0x104; +$BTN_5 = 0x105; +$BTN_6 = 0x106; +$BTN_7 = 0x107; +$BTN_8 = 0x108; +$BTN_9 = 0x109; + +$BTN_MOUSE = 0x110; +$BTN_LEFT = 0x110; +$BTN_RIGHT = 0x111; +$BTN_MIDDLE = 0x112; +$BTN_SIDE = 0x113; +$BTN_EXTRA = 0x114; +$BTN_FORWARD = 0x115; +$BTN_BACK = 0x116; +$BTN_TASK = 0x117; + +$BTN_JOYSTICK = 0x120; +$BTN_TRIGGER = 0x120; +$BTN_THUMB = 0x121; +$BTN_THUMB2 = 0x122; +$BTN_TOP = 0x123; +$BTN_TOP2 = 0x124; +$BTN_PINKIE = 0x125; +$BTN_BASE = 0x126; +$BTN_BASE2 = 0x127; +$BTN_BASE3 = 0x128; +$BTN_BASE4 = 0x129; +$BTN_BASE5 = 0x12a; +$BTN_BASE6 = 0x12b; +$BTN_DEAD = 0x12f; + +$BTN_GAMEPAD = 0x130; +$BTN_A = 0x130; +$BTN_B = 0x131; +$BTN_C = 0x132; +$BTN_X = 0x133; +$BTN_Y = 0x134; +$BTN_Z = 0x135; +$BTN_TL = 0x136; +$BTN_TR = 0x137; +$BTN_TL2 = 0x138; +$BTN_TR2 = 0x139; +$BTN_SELECT = 0x13a; +$BTN_START = 0x13b; +$BTN_MODE = 0x13c; +$BTN_THUMBL = 0x13d; +$BTN_THUMBR = 0x13e; + +$BTN_DIGI = 0x140; +$BTN_TOOL_PEN = 0x140; +$BTN_TOOL_RUBBER = 0x141; +$BTN_TOOL_BRUSH = 0x142; +$BTN_TOOL_PENCIL = 0x143; +$BTN_TOOL_AIRBRUSH = 0x144; +$BTN_TOOL_FINGER = 0x145; +$BTN_TOOL_MOUSE = 0x146; +$BTN_TOOL_LENS = 0x147; +$BTN_TOUCH = 0x14a; +$BTN_STYLUS = 0x14b; +$BTN_STYLUS2 = 0x14c; +$BTN_TOOL_DOUBLETAP = 0x14d; +$BTN_TOOL_TRIPLETAP = 0x14e; + +$BTN_WHEEL = 0x150; +$BTN_GEAR_DOWN = 0x150; +$BTN_GEAR_UP = 0x151; + +$SYN_REPORT = 0; +$SYN_CONFIG = 1; +$SYN_MT_REPORT = 2; + +$KEY_RESERVED = 0; +$KEY_ESC = 1; +$KEY_1 = 2; +$KEY_2 = 3; +$KEY_3 = 4; +$KEY_4 = 5; +$KEY_5 = 6; +$KEY_6 = 7; +$KEY_7 = 8; +$KEY_8 = 9; +$KEY_9 = 10; +$KEY_0 = 11; +$KEY_MINUS = 12; +$KEY_EQUAL = 13; +$KEY_BACKSPACE = 14; +$KEY_TAB = 15; +$KEY_Q = 16; +$KEY_W = 17; +$KEY_E = 18; +$KEY_R = 19; +$KEY_T = 20; +$KEY_Y = 21; +$KEY_U = 22; +$KEY_I = 23; +$KEY_O = 24; +$KEY_P = 25; +$KEY_LEFTBRACE = 26; +$KEY_RIGHTBRACE = 27; +$KEY_ENTER = 28; +$KEY_LEFTCTRL = 29; +$KEY_A = 30; +$KEY_S = 31; +$KEY_D = 32; +$KEY_F = 33; +$KEY_G = 34; +$KEY_H = 35; +$KEY_J = 36; +$KEY_K = 37; +$KEY_L = 38; +$KEY_SEMICOLON = 39; +$KEY_APOSTROPHE = 40; +$KEY_GRAVE = 41; +$KEY_LEFTSHIFT = 42; +$KEY_BACKSLASH = 43; +$KEY_Z = 44; +$KEY_X = 45; +$KEY_C = 46; +$KEY_V = 47; +$KEY_B = 48; +$KEY_N = 49; +$KEY_M = 50; +$KEY_COMMA = 51; +$KEY_DOT = 52; +$KEY_SLASH = 53; +$KEY_RIGHTSHIFT = 54; +$KEY_KPASTERISK = 55; +$KEY_LEFTALT = 56; +$KEY_SPACE = 57; +$KEY_CAPSLOCK = 58; +$KEY_F1 = 59; +$KEY_F2 = 60; +$KEY_F3 = 61; +$KEY_F4 = 62; +$KEY_F5 = 63; +$KEY_F6 = 64; +$KEY_F7 = 65; +$KEY_F8 = 66; +$KEY_F9 = 67; +$KEY_F10 = 68; +$KEY_NUMLOCK = 69; +$KEY_SCROLLLOCK = 70; +$KEY_KP7 = 71; +$KEY_KP8 = 72; +$KEY_KP9 = 73; +$KEY_KPMINUS = 74; +$KEY_KP4 = 75; +$KEY_KP5 = 76; +$KEY_KP6 = 77; +$KEY_KPPLUS = 78; +$KEY_KP1 = 79; +$KEY_KP2 = 80; +$KEY_KP3 = 81; +$KEY_KP0 = 82; +$KEY_KPDOT = 83; +$KEY_103RD = 84; +$KEY_F13 = 85; +$KEY_102ND = 86; +$KEY_F11 = 87; +$KEY_F12 = 88; +$KEY_F14 = 89; +$KEY_F15 = 90; +$KEY_F16 = 91; +$KEY_F17 = 92; +$KEY_F18 = 93; +$KEY_F19 = 94; +$KEY_F20 = 95; +$KEY_KPENTER = 96; +$KEY_RIGHTCTRL = 97; +$KEY_KPSLASH = 98; +$KEY_SYSRQ = 99; +$KEY_RIGHTALT = 100; +$KEY_LINEFEED = 101; +$KEY_HOME = 102; +$KEY_UP = 103; +$KEY_PAGEUP = 104; +$KEY_LEFT = 105; +$KEY_RIGHT = 106; +$KEY_END = 107; +$KEY_DOWN = 108; +$KEY_PAGEDOWN = 109; +$KEY_INSERT = 110; +$KEY_DELETE = 111; +$KEY_MACRO = 112; +$KEY_MUTE = 113; +$KEY_VOLUMEDOWN = 114; +$KEY_VOLUMEUP = 115; +$KEY_POWER = 116; +$KEY_KPEQUAL = 117; +$KEY_KPPLUSMINUS = 118; +$KEY_PAUSE = 119; +$KEY_F21 = 120; +$KEY_F22 = 121; +$KEY_F23 = 122; +$KEY_F24 = 123; +$KEY_KPCOMMA = 124; +$KEY_LEFTMETA = 125; +$KEY_RIGHTMETA = 126; +$KEY_COMPOSE = 127; +$KEY_STOP = 128; +$KEY_AGAIN = 129; +$KEY_PROPS = 130; +$KEY_UNDO = 131; +$KEY_FRONT = 132; +$KEY_COPY = 133; +$KEY_OPEN = 134; +$KEY_PASTE = 135; +$KEY_FIND = 136; +$KEY_CUT = 137; +$KEY_HELP = 138; +$KEY_MENU = 139; +$KEY_CALC = 140; +$KEY_SETUP = 141; +$KEY_SLEEP = 142; +$KEY_WAKEUP = 143; +$KEY_FILE = 144; +$KEY_SENDFILE = 145; +$KEY_DELETEFILE = 146; +$KEY_XFER = 147; +$KEY_PROG1 = 148; +$KEY_PROG2 = 149; +$KEY_WWW = 150; +$KEY_MSDOS = 151; +$KEY_COFFEE = 152; +$KEY_DIRECTION = 153; +$KEY_CYCLEWINDOWS = 154; +$KEY_MAIL = 155; +$KEY_BOOKMARKS = 156; +$KEY_COMPUTER = 157; +$KEY_BACK = 158; +$KEY_FORWARD = 159; +$KEY_CLOSECD = 160; +$KEY_EJECTCD = 161; +$KEY_EJECTCLOSECD = 162; +$KEY_NEXTSONG = 163; +$KEY_PLAYPAUSE = 164; +$KEY_PREVIOUSSONG = 165; +$KEY_STOPCD = 166; +$KEY_RECORD = 167; +$KEY_REWIND = 168; +$KEY_PHONE = 169; +$KEY_ISO = 170; +$KEY_CONFIG = 171; +$KEY_HOMEPAGE = 172; +$KEY_REFRESH = 173; +$KEY_EXIT = 174; +$KEY_MOVE = 175; +$KEY_EDIT = 176; +$KEY_SCROLLUP = 177; +$KEY_SCROLLDOWN = 178; +$KEY_KPLEFTPAREN = 179; +$KEY_KPRIGHTPAREN = 180; +$KEY_INTL1 = 181; +$KEY_INTL2 = 182; +$KEY_INTL3 = 183; +$KEY_INTL4 = 184; +$KEY_INTL5 = 185; +$KEY_INTL6 = 186; +$KEY_INTL7 = 187; +$KEY_INTL8 = 188; +$KEY_INTL9 = 189; +$KEY_LANG1 = 190; +$KEY_LANG2 = 191; +$KEY_LANG3 = 192; +$KEY_LANG4 = 193; +$KEY_LANG5 = 194; +$KEY_LANG6 = 195; +$KEY_LANG7 = 196; +$KEY_LANG8 = 197; +$KEY_LANG9 = 198; +$KEY_PLAYCD = 200; +$KEY_PAUSECD = 201; +$KEY_PROG3 = 202; +$KEY_PROG4 = 203; +$KEY_SUSPEND = 205; +$KEY_CLOSE = 206; +$KEY_PLAY = 207; +$KEY_FASTFORWARD = 208; +$KEY_BASSBOOST = 209; +$KEY_PRINT = 210; +$KEY_HP = 211; +$KEY_CAMERA = 212; +$KEY_SOUND = 213; +$KEY_QUESTION = 214; +$KEY_EMAIL = 215; +$KEY_CHAT = 216; +$KEY_SEARCH = 217; +$KEY_CONNECT = 218; +$KEY_FINANCE = 219; +$KEY_SPORT = 220; +$KEY_SHOP = 221; +$KEY_ALTERASE = 222; +$KEY_CANCEL = 223; +$KEY_BRIGHTNESSDOWN = 224; +$KEY_BRIGHTNESSUP = 225; +$KEY_MEDIA = 226; +$KEY_UNKNOWN = 240; +$KEY_OK = 0x160; +$KEY_SELECT = 0x161; +$KEY_GOTO = 0x162; +$KEY_CLEAR = 0x163; +$KEY_POWER2 = 0x164; +$KEY_OPTION = 0x165; +$KEY_INFO = 0x166; +$KEY_TIME = 0x167; +$KEY_VENDOR = 0x168; +$KEY_ARCHIVE = 0x169; +$KEY_PROGRAM = 0x16a; +$KEY_CHANNEL = 0x16b; +$KEY_FAVORITES = 0x16c; +$KEY_EPG = 0x16d; +$KEY_PVR = 0x16e; +$KEY_MHP = 0x16f; +$KEY_LANGUAGE = 0x170; +$KEY_TITLE = 0x171; +$KEY_SUBTITLE = 0x172; +$KEY_ANGLE = 0x173; +$KEY_ZOOM = 0x174; +$KEY_MODE = 0x175; +$KEY_KEYBOARD = 0x176; +$KEY_SCREEN = 0x177; +$KEY_PC = 0x178; +$KEY_TV = 0x179; +$KEY_TV2 = 0x17a; +$KEY_VCR = 0x17b; +$KEY_VCR2 = 0x17c; +$KEY_SAT = 0x17d; +$KEY_SAT2 = 0x17e; +$KEY_CD = 0x17f; +$KEY_TAPE = 0x180; +$KEY_RADIO = 0x181; +$KEY_TUNER = 0x182; +$KEY_PLAYER = 0x183; +$KEY_TEXT = 0x184; +$KEY_DVD = 0x185; +$KEY_AUX = 0x186; +$KEY_MP3 = 0x187; +$KEY_AUDIO = 0x188; +$KEY_VIDEO = 0x189; +$KEY_DIRECTORY = 0x18a; +$KEY_LIST = 0x18b; +$KEY_MEMO = 0x18c; +$KEY_CALENDAR = 0x18d; +$KEY_RED = 0x18e; +$KEY_GREEN = 0x18f; +$KEY_YELLOW = 0x190; +$KEY_BLUE = 0x191; +$KEY_CHANNELUP = 0x192; +$KEY_CHANNELDOWN = 0x193; +$KEY_FIRST = 0x194; +$KEY_LAST = 0x195; +$KEY_AB = 0x196; +$KEY_NEXT = 0x197; +$KEY_RESTART = 0x198; +$KEY_SLOW = 0x199; +$KEY_SHUFFLE = 0x19a; +$KEY_BREAK = 0x19b; +$KEY_PREVIOUS = 0x19c; +$KEY_DIGITS = 0x19d; +$KEY_TEEN = 0x19e; +$KEY_TWEN = 0x19f; +$KEY_DEL_EOL = 0x1c0; +$KEY_DEL_EOS = 0x1c1; +$KEY_INS_LINE = 0x1c2; +$KEY_DEL_LINE = 0x1c3; +$KEY_MAX = 0x1ff; + + + $key_lookup{XK_Escape} = $KEY_ESC; + $key_lookup{XK_1} = $KEY_1; + $key_lookup{XK_2} = $KEY_2; + $key_lookup{XK_3} = $KEY_3; + $key_lookup{XK_4} = $KEY_4; + $key_lookup{XK_5} = $KEY_5; + $key_lookup{XK_6} = $KEY_6; + $key_lookup{XK_7} = $KEY_7; + $key_lookup{XK_8} = $KEY_8; + $key_lookup{XK_9} = $KEY_9; + $key_lookup{XK_0} = $KEY_0; + $key_lookup{XK_exclam} = $KEY_1; + $key_lookup{XK_at} = $KEY_2; + $key_lookup{XK_numbersign} = $KEY_3; + $key_lookup{XK_dollar} = $KEY_4; + $key_lookup{XK_percent} = $KEY_5; + $key_lookup{XK_asciicircum} = $KEY_6; + $key_lookup{XK_ampersand} = $KEY_7; + $key_lookup{XK_asterisk} = $KEY_8; + $key_lookup{XK_parenleft} = $KEY_9; + $key_lookup{XK_parenright} = $KEY_0; + $key_lookup{XK_minus} = $KEY_MINUS; + $key_lookup{XK_underscore} = $KEY_MINUS; + $key_lookup{XK_equal} = $KEY_EQUAL; + $key_lookup{XK_plus} = $KEY_EQUAL; + $key_lookup{XK_BackSpace} = $KEY_BACKSPACE; + $key_lookup{XK_Tab} = $KEY_TAB; + $key_lookup{XK_q} = $KEY_Q; + $key_lookup{XK_Q} = $KEY_Q; + $key_lookup{XK_w} = $KEY_W; + $key_lookup{XK_W} = $KEY_W; + $key_lookup{XK_e} = $KEY_E; + $key_lookup{XK_E} = $KEY_E; + $key_lookup{XK_r} = $KEY_R; + $key_lookup{XK_R} = $KEY_R; + $key_lookup{XK_t} = $KEY_T; + $key_lookup{XK_T} = $KEY_T; + $key_lookup{XK_y} = $KEY_Y; + $key_lookup{XK_Y} = $KEY_Y; + $key_lookup{XK_u} = $KEY_U; + $key_lookup{XK_U} = $KEY_U; + $key_lookup{XK_i} = $KEY_I; + $key_lookup{XK_I} = $KEY_I; + $key_lookup{XK_o} = $KEY_O; + $key_lookup{XK_O} = $KEY_O; + $key_lookup{XK_p} = $KEY_P; + $key_lookup{XK_P} = $KEY_P; + $key_lookup{XK_braceleft} = $KEY_LEFTBRACE; + $key_lookup{XK_braceright} = $KEY_RIGHTBRACE; + $key_lookup{XK_bracketleft} = $KEY_LEFTBRACE; + $key_lookup{XK_bracketright} = $KEY_RIGHTBRACE; + $key_lookup{XK_Return} = $KEY_ENTER; + $key_lookup{XK_Control_L} = $KEY_LEFTCTRL; + $key_lookup{XK_a} = $KEY_A; + $key_lookup{XK_A} = $KEY_A; + $key_lookup{XK_s} = $KEY_S; + $key_lookup{XK_S} = $KEY_S; + $key_lookup{XK_d} = $KEY_D; + $key_lookup{XK_D} = $KEY_D; + $key_lookup{XK_f} = $KEY_F; + $key_lookup{XK_F} = $KEY_F; + $key_lookup{XK_g} = $KEY_G; + $key_lookup{XK_G} = $KEY_G; + $key_lookup{XK_h} = $KEY_H; + $key_lookup{XK_H} = $KEY_H; + $key_lookup{XK_j} = $KEY_J; + $key_lookup{XK_J} = $KEY_J; + $key_lookup{XK_k} = $KEY_K; + $key_lookup{XK_K} = $KEY_K; + $key_lookup{XK_l} = $KEY_L; + $key_lookup{XK_L} = $KEY_L; + $key_lookup{XK_semicolon} = $KEY_SEMICOLON; + $key_lookup{XK_colon} = $KEY_SEMICOLON; + $key_lookup{XK_apostrophe} = $KEY_APOSTROPHE; + $key_lookup{XK_quotedbl} = $KEY_APOSTROPHE; + $key_lookup{XK_grave} = $KEY_GRAVE; + $key_lookup{XK_asciitilde} = $KEY_GRAVE; + $key_lookup{XK_Shift_L} = $KEY_LEFTSHIFT; + $key_lookup{XK_backslash} = $KEY_BACKSLASH; + $key_lookup{XK_bar} = $KEY_BACKSLASH; + $key_lookup{XK_z} = $KEY_Z; + $key_lookup{XK_Z} = $KEY_Z; + $key_lookup{XK_x} = $KEY_X; + $key_lookup{XK_X} = $KEY_X; + $key_lookup{XK_c} = $KEY_C; + $key_lookup{XK_C} = $KEY_C; + $key_lookup{XK_v} = $KEY_V; + $key_lookup{XK_V} = $KEY_V; + $key_lookup{XK_b} = $KEY_B; + $key_lookup{XK_B} = $KEY_B; + $key_lookup{XK_n} = $KEY_N; + $key_lookup{XK_N} = $KEY_N; + $key_lookup{XK_m} = $KEY_M; + $key_lookup{XK_M} = $KEY_M; + $key_lookup{XK_comma} = $KEY_COMMA; + $key_lookup{XK_less} = $KEY_COMMA; + $key_lookup{XK_period} = $KEY_DOT; + $key_lookup{XK_greater} = $KEY_DOT; + $key_lookup{XK_slash} = $KEY_SLASH; + $key_lookup{XK_question} = $KEY_SLASH; + $key_lookup{XK_Shift_R} = $KEY_RIGHTSHIFT; + $key_lookup{XK_KP_Multiply} = $KEY_KPASTERISK; + $key_lookup{XK_Alt_L} = $KEY_LEFTALT; + $key_lookup{XK_space} = $KEY_SPACE; + $key_lookup{XK_Caps_Lock} = $KEY_CAPSLOCK; + $key_lookup{XK_F1} = $KEY_F1; + $key_lookup{XK_F2} = $KEY_F2; + $key_lookup{XK_F3} = $KEY_F3; + $key_lookup{XK_F4} = $KEY_F4; + $key_lookup{XK_F5} = $KEY_F5; + $key_lookup{XK_F6} = $KEY_F6; + $key_lookup{XK_F7} = $KEY_F7; + $key_lookup{XK_F8} = $KEY_F8; + $key_lookup{XK_F9} = $KEY_F9; + $key_lookup{XK_F10} = $KEY_F10; + $key_lookup{XK_Num_Lock} = $KEY_NUMLOCK; + $key_lookup{XK_Scroll_Lock} = $KEY_SCROLLLOCK; + $key_lookup{XK_KP_7} = $KEY_KP7; + $key_lookup{XK_KP_8} = $KEY_KP8; + $key_lookup{XK_KP_9} = $KEY_KP9; + $key_lookup{XK_KP_Subtract} = $KEY_KPMINUS; + $key_lookup{XK_KP_4} = $KEY_KP4; + $key_lookup{XK_KP_5} = $KEY_KP5; + $key_lookup{XK_KP_6} = $KEY_KP6; + $key_lookup{XK_KP_Add} = $KEY_KPPLUS; + $key_lookup{XK_KP_1} = $KEY_KP1; + $key_lookup{XK_KP_2} = $KEY_KP2; + $key_lookup{XK_KP_3} = $KEY_KP3; + $key_lookup{XK_KP_0} = $KEY_KP0; + $key_lookup{XK_KP_Decimal} = $KEY_KPDOT; + $key_lookup{XK_F13} = $KEY_F13; + $key_lookup{XK_F11} = $KEY_F11; + $key_lookup{XK_F12} = $KEY_F12; + $key_lookup{XK_F14} = $KEY_F14; + $key_lookup{XK_F15} = $KEY_F15; + $key_lookup{XK_F16} = $KEY_F16; + $key_lookup{XK_F17} = $KEY_F17; + $key_lookup{XK_F18} = $KEY_F18; + $key_lookup{XK_F19} = $KEY_F19; + $key_lookup{XK_F20} = $KEY_F20; + $key_lookup{XK_KP_Enter} = $KEY_KPENTER; + $key_lookup{XK_Control_R} = $KEY_RIGHTCTRL; + $key_lookup{XK_KP_Divide} = $KEY_KPSLASH; + $key_lookup{XK_Sys_Req} = $KEY_SYSRQ; + $key_lookup{XK_Alt_R} = $KEY_RIGHTALT; + $key_lookup{XK_Linefeed} = $KEY_LINEFEED; + $key_lookup{XK_Home} = $KEY_HOME; + $key_lookup{XK_Up} = $KEY_UP; + $key_lookup{XK_Page_Up} = $KEY_PAGEUP; + $key_lookup{XK_Left} = $KEY_LEFT; + $key_lookup{XK_Right} = $KEY_RIGHT; + $key_lookup{XK_End} = $KEY_END; + $key_lookup{XK_Down} = $KEY_DOWN; + $key_lookup{XK_Page_Down} = $KEY_PAGEDOWN; + $key_lookup{XK_Insert} = $KEY_INSERT; + $key_lookup{XK_Delete} = $KEY_DELETE; + $key_lookup{XK_KP_Equal} = $KEY_KPEQUAL; + $key_lookup{XK_Pause} = $KEY_PAUSE; + $key_lookup{XK_F21} = $KEY_F21; + $key_lookup{XK_F22} = $KEY_F22; + $key_lookup{XK_F23} = $KEY_F23; + $key_lookup{XK_F24} = $KEY_F24; + $key_lookup{XK_KP_Separator} = $KEY_KPCOMMA; + $key_lookup{XK_Meta_L} = $KEY_LEFTMETA; + $key_lookup{XK_Meta_R} = $KEY_RIGHTMETA; + $key_lookup{XK_Multi_key} = $KEY_COMPOSE; + +$ABS_MAX = 63; + +$UI_DEV_CREATE = 0x5501; +$UI_DEV_DESTROY = 0x5502; +$UI_SET_EVBIT = 0x40045564; +$UI_SET_KEYBIT = 0x40045565; +$UI_SET_RELBIT = 0x40045566; +$UI_SET_ABSBIT = 0x40045567; + +# FIXME: time hires, etc. +$linux_gettimeofday_syscall = 78; + +$O_RDONLY = 00; +$O_WRONLY = 01; +$O_RDWR = 02; +$O_NDELAY = 04000; + +} diff --git a/x11vnc/pointer.c b/x11vnc/pointer.c index c57d2d7..f2995c3 100644 --- a/x11vnc/pointer.c +++ b/x11vnc/pointer.c @@ -620,24 +620,24 @@ static void pipe_pointer(int mask, int x, int y, rfbClientPtr client) { if (mask == button_mask) { strcat(hint, "None"); } else { - int i, old, new, m = 1, cnt = 0; + int i, old, newb, m = 1, cnt = 0; for (i=0; ihttpDir) { return; @@ -619,8 +619,8 @@ static void reset_httpport(int old, int new) { } } -static void reset_rfbport(int old, int new) { - int rp = new; +static void reset_rfbport(int old, int newp) { + int rp = newp; if (inetd) { rfbLog("reset_rfbport: cannot set rfbport: %d in inetd.\n", rp); @@ -2303,7 +2303,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { * safe_remote_only but at least the command names * are fixed. */ - char *new; + char *newc; int doit = 1; COLON_CHECK("solid_color:") if (query) { @@ -2313,19 +2313,19 @@ char *process_remote_cmd(char *cmd, int stringonly) { } p += strlen("solid_color:"); if (*p != '\0') { - new = strdup(p); + newc = strdup(p); } else { - new = strdup(solid_default); + newc = strdup(solid_default); } - rfbLog("remote_cmd: solid %s -> %s\n", NONUL(solid_str), new); + rfbLog("remote_cmd: solid %s -> %s\n", NONUL(solid_str), newc); if (solid_str) { - if (!strcmp(solid_str, new)) { + if (!strcmp(solid_str, newc)) { doit = 0; } free(solid_str); } - solid_str = new; + solid_str = newc; use_solid_bg = 1; if (raw_fb && !macosx_console) set_raw_fb_params(0); @@ -4213,6 +4213,24 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("enabled grab_ptr\n"); goto done; } + if (!strcmp(p, "ungrabboth")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, ungrab_both); + goto qry; + } + ungrab_both = 1; + rfbLog("enabled ungrab_both\n"); + goto done; + } + if (!strcmp(p, "noungrabboth")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !ungrab_both); + goto qry; + } + ungrab_both = 0; + rfbLog("disabled ungrab_both\n"); + goto done; + } if (!strcmp(p, "nograbptr")) { int orig = grab_ptr; if (query) { diff --git a/x11vnc/scan.c b/x11vnc/scan.c index b8fa645..1fb7883 100644 --- a/x11vnc/scan.c +++ b/x11vnc/scan.c @@ -2961,7 +2961,17 @@ static void nap_check(int tile_cnt) { now = time(NULL); if (screen_blank > 0) { - int dt_ev, dt_fbu, ms = 2000; + int dt_ev, dt_fbu; + static int ms = 0; + if (ms == 0) { + ms = 2000; + if (getenv("X11VNC_SB_FACTOR")) { + ms = ms * atof(getenv("X11VNC_SB_FACTOR")); + } + if (ms <= 0) { + ms = 2000; + } + } /* if no activity, pause here for a second or so. */ dt_ev = (int) (now - last_event); diff --git a/x11vnc/screen.c b/x11vnc/screen.c index 6bada90..067d144 100644 --- a/x11vnc/screen.c +++ b/x11vnc/screen.c @@ -1461,7 +1461,19 @@ char *vnc_reflect_guess(char *str, char **raw_fb_addr) { char *str0 = strdup(str); if (client == NULL) { - client = rfbGetClient(8, 3, 4); + int bitsPerSample = 8; + int samplesPerPixel = 3; + int bytesPerPixel = 4; + char *s; + s = getenv("X11VNC_REFLECT_bitsPerSample"); + if (s) bitsPerSample = atoi(s); + s = getenv("X11VNC_REFLECT_samplesPerPixel"); + if (s) samplesPerPixel = atoi(s); + s = getenv("X11VNC_REFLECT_bytesPerPixel"); + if (s) bytesPerPixel = atoi(s); + rfbLog("rfbGetClient(bitsPerSample=%d, samplesPerPixel=%d, bytesPerPixel=%d)\n", + bitsPerSample, samplesPerPixel, bytesPerPixel); + client = rfbGetClient(bitsPerSample, samplesPerPixel, bytesPerPixel); } rfbLog("rawfb: %s\n", str); @@ -2086,16 +2098,16 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n"); /* hmmm, not following directions, see if map: applies */ struct stat sbuf; if (stat(str, &sbuf) == 0) { - char *new; + char *newstr; int len = strlen("map:") + strlen(str) + 1; rfbLog("no type prefix: %s\n", raw_fb_str); rfbLog(" but file exists, so assuming: map:%s\n", raw_fb_str); - new = (char *) malloc(len); - strcpy(new, "map:"); - strcat(new, str); + newstr = (char *) malloc(len); + strcpy(newstr, "map:"); + strcat(newstr, str); free(str); - str = new; + str = newstr; } } diff --git a/x11vnc/sslhelper.c b/x11vnc/sslhelper.c index ca5168f..7057615 100644 --- a/x11vnc/sslhelper.c +++ b/x11vnc/sslhelper.c @@ -125,17 +125,17 @@ char *get_saved_pem(char *save, int create) { sprintf(path, "%s/server%s.pem", cdir, s); if (stat(path, &sbuf) != 0) { - char *new = NULL; + char *new_name = NULL; if (create) { if (inetd || opts_bg) { set_env("GENCERT_NOPROMPT", "1"); } - new = create_tmp_pem(path, prompt); + new_name = create_tmp_pem(path, prompt); if (!getenv("X11VNC_SSL_NO_PASSPHRASE") && !inetd && !opts_bg) { - sslEncKey(new, 0); + sslEncKey(new_name, 0); } } - return new; + return new_name; } if (! quiet) { @@ -332,9 +332,12 @@ char *create_tmp_pem(char *pathin, int prompt) { sprintf(str, tmpl, C, L, OU, O, CN, EM); cnf_fd = mkstemp(cnf); + if (cnf_fd < 0) { + return NULL; + } pem_fd = mkstemp(pem); - - if (cnf_fd < 0 || pem_fd < 0) { + if (pem_fd < 0) { + close(cnf_fd); return NULL; } diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h index 9c74d5f..6557a9b 100644 --- a/x11vnc/ssltools.h +++ b/x11vnc/ssltools.h @@ -847,15 +847,18 @@ char find_display[] = "prdpy () {\n" " d1=$1\n" " chvt0=\"\"\n" +" if [ \"X$FIND_DISPLAY_NO_VT_FIND\" != \"X\" ]; then\n" +" :\n" " # we can only do chvt on Linux:\n" -" if [ \"X$uname\" = \"XLinux\" ]; then\n" +" elif [ \"X$uname\" = \"XLinux\" ]; then\n" " d2=$d1\n" " d3=`echo \"$d2\" | sed -e 's/^.*:/:/' -e 's/\\..*$//'`\n" " d4=\"($d2|$d3)\"\n" "\n" " # vt is usually in X server line:\n" " #\n" -" vt=`ps wwwwwaux | grep X | egrep -v 'startx|xinit' | egrep \" $d4 \" | egrep ' vt([789]|[1-9][0-9][0-9]*) ' | grep -v grep | head -n 1`\n" +" ps_tmp=`ps wwaux | grep X`\n" +" vt=`echo \"$ps_tmp\" | grep X | egrep -v 'startx|xinit' | egrep \" $d4 \" | egrep ' vt([789]|[1-9][0-9][0-9]*) ' | grep -v grep | head -n 1`\n" "\n" " if [ \"X$vt\" != \"X\" ]; then\n" " # strip it out and add it.\n" @@ -865,7 +868,7 @@ char find_display[] = " fi\n" " else\n" " # otherwise look for tty:\n" -" vt=`ps wwwwwaux | grep X | egrep \" $d4 \" | egrep ' tty([789]|[1-9][0-9][0-9]*) ' | grep -v grep | head -n 1`\n" +" vt=`echo \"$ps_tmp\" | grep X | egrep \" $d4 \" | egrep ' tty([789]|[1-9][0-9][0-9]*) ' | grep -v grep | head -n 1`\n" " if [ \"X$vt\" != \"X\" ]; then\n" " vt=`echo \"$vt\" | sed -e 's/^.* tty\\([0-9][0-9]*\\) .*$/\\1/'`\n" " if echo \"$vt\" | grep '^[0-9][0-9]*$' > /dev/null; then\n" @@ -873,8 +876,12 @@ char find_display[] = " fi\n" " else\n" " # otherwise try lsof:\n" -" pvt=`ps wwwwwaux | grep X | egrep -v 'startx|xinit' | egrep \" $d4 \" | head -n 1 | awk '{print $2}'`\n" -" if [ \"X$pvt\" != \"X\" ]; then\n" +" pvt=`echo \"$ps_tmp\" | grep X | egrep -v 'startx|xinit' | egrep \" $d4 \" | head -n 1 | awk '{print $2}'`\n" +" if [ \"X$FIND_DISPLAY_NO_LSOF\" != \"X\" ]; then\n" +" if [ \"X$pvt\" != \"X\" ]; then\n" +" chvt0=\",XPID=$pvt\"\n" +" fi\n" +" elif [ \"X$pvt\" != \"X\" ]; then\n" " vt=`lsof -b -p \"$pvt\" 2>/dev/null | egrep '/dev/tty([789]|[1-9][0-9][0-9]*)$' | grep -v grep | head -n 1 | awk '{print $NF}' | sed -e 's,/dev/tty,,'`\n" " if echo \"$vt\" | grep '^[0-9][0-9]*$' > /dev/null; then\n" " chvt0=\",VT=$vt\"\n" @@ -902,9 +909,9 @@ char find_display[] = "if [ \"X$uname\" = \"XDarwin\" ]; then\n" " psout=`ps aux 2>/dev/null | grep -wv PID | grep -v grep`\n" "elif [ \"X$uname\" = \"XLinux\" -o \"X$is_bsd\" = \"X1\" ]; then\n" -" psout=`ps wwwaux 2>/dev/null | grep -wv PID | grep -v grep`\n" +" psout=`ps wwaux 2>/dev/null | grep -wv PID | grep -v grep`\n" "elif [ \"X$uname\" = \"XSunOS\" -a -x /usr/ucb/ps ]; then\n" -" psout=`/usr/ucb/ps wwwaux 2>/dev/null | grep -wv PID | grep -v grep`\n" +" psout=`/usr/ucb/ps wwaux 2>/dev/null | grep -wv PID | grep -v grep`\n" "else\n" " psout=`ps -ef 2>/dev/null | grep -wv PID | grep -v grep`\n" "fi\n" @@ -1192,6 +1199,8 @@ char find_display[] = "\n" "# try the items in the list:\n" "#\n" +"nsout_trim=`echo \"$nsout\" | grep \"/tmp/.X11-unix/\"`\n" +"#\n" "for p in $list\n" "do\n" " xa=`echo \"$p\" | awk -F, '{print $2}'`\n" @@ -1205,7 +1214,7 @@ char find_display[] = " # check for the local X11 files:\n" " xd=\"/tmp/.X11-unix/X$d\"\n" " if [ -r \"$xd\" -o -w \"$xd\" -o -x \"$xd\" ]; then\n" -" if echo \"$nsout\" | grep \"/tmp/.X11-unix/X$d[ ]*\\$\" > /dev/null; then\n" +" if echo \"$nsout_trim\" | grep \"/tmp/.X11-unix/X$d[ ]*\\$\" > /dev/null; then\n" " ok=1\n" " fi\n" " fi\n" @@ -1473,6 +1482,7 @@ char create_display[] = "COLUMNS=256\n" "export COLUMNS\n" "\n" +"LC_ALL_save=$LC_ALL\n" "LC_ALL=C\n" "export LC_ALL\n" "\n" @@ -1491,11 +1501,12 @@ char create_display[] = " if [ \"X$have_netstat\" != \"X\" ]; then\n" " nsout=`$have_netstat -an`\n" " fi\n" +" nsout_trim=`echo \"$nsout\" | grep \"/tmp/.X11-unix/\"`\n" " while [ $try -lt $sry ]\n" " do\n" " tlock=\"/tmp/.X${try}-lock\"\n" " if [ -r $tlock ]; then\n" -" if echo \"$nsout\" | grep \"/tmp/.X11-unix/X${try}[ ]*\\$\" > /dev/null; then\n" +" if echo \"$nsout_trim\" | grep \"/tmp/.X11-unix/X${try}[ ]*\\$\" > /dev/null; then\n" " :\n" " else\n" " pid=`head -n 1 $tlock 2>/dev/null | sed -e 's/[ ]//g' | grep '^[0-9][0-9]*$'`\n" @@ -1513,7 +1524,7 @@ char create_display[] = " fi\n" " fi\n" " if [ ! -f $tlock ]; then\n" -" if echo \"$nsout\" | grep \"/tmp/.X11-unix/X${try}[ ]*\\$\" > /dev/null; then\n" +" if echo \"$nsout_trim\" | grep \"/tmp/.X11-unix/X${try}[ ]*\\$\" > /dev/null; then\n" " :\n" " else\n" " n=$try\n" @@ -1829,6 +1840,16 @@ char create_display[] = " echo \"\" 1>&2\n" "}\n" "\n" +"put_back_LC_ALL() {\n" +" if [ \"X$X11VNC_CREATE_LC_ALL_C_OK\" = \"X\" ]; then\n" +" if [ \"X$LC_ALL_save\" = \"X\" ]; then\n" +" unset LC_ALL\n" +" else\n" +" LC_ALL=\"$LC_ALL_save\"\n" +" fi\n" +" fi\n" +"}\n" +"\n" "server() {\n" " authfile=`auth`\n" " sess=`findsession`\n" @@ -1894,6 +1915,7 @@ char create_display[] = " # ns=2\n" " #fi\n" "\n" +"\n" " if [ \"X$use_xdmcp_query\" = \"X1\" ]; then\n" " # we cannot use -nolisten tcp\n" " if [ \"X$FD_XDMCP_IF\" != \"X\" ]; then\n" @@ -1908,6 +1930,7 @@ char create_display[] = " lhost=localhost\n" " fi\n" " echo \"$* -once -query $lhost $FD_OPTS\" 1>&2\n" +" put_back_LC_ALL\n" " if [ \"X$have_root\" != \"X\" ]; then\n" " if [ -r $authfile ]; then\n" " $have_nohup $* -once -query $lhost -auth $authfile $FD_OPTS 1>&2 &\n" @@ -1932,6 +1955,7 @@ char create_display[] = " sxcmd=$have_startx\n" " fi\n" " echo \"$sxcmd $sess -- $* $nolisten -auth $authfile $FD_OPTS\" 1>&2\n" +" put_back_LC_ALL\n" " if [ \"X$have_root\" != \"X\" ]; then\n" " $sxcmd $sess -- $* $nolisten -auth $authfile $FD_OPTS 1>&2 &\n" " else\n" @@ -1947,6 +1971,7 @@ char create_display[] = " else\n" " # need to emulate startx/xinit ourselves...\n" " echo \"$* $nolisten -auth $authfile $FD_OPTS\" 1>&2\n" +" put_back_LC_ALL\n" " if [ \"X$have_root\" != \"X\" ]; then\n" " $have_nohup $* $nolisten -auth $authfile $FD_OPTS 1>&2 &\n" " pid=$!\n" @@ -1964,10 +1989,14 @@ char create_display[] = " $have_nohup sh -c \"(sleep 3; $sess)\" 1>&2 &\n" " fi\n" " fi\n" +"\n" +" LC_ALL=C\n" +" export LC_ALL\n" +"\n" " if uname | grep SunOS > /dev/null; then\n" -" $have_nohup sh -c \"(sleep 60; rm -f $rmf)\" 1>&2 &\n" +" $have_nohup sh -c \"(sleep 150; rm -f $rmf)\" 1>&2 &\n" " else\n" -" $have_nohup sh -c \"(sleep 60; rm -f $rmf $authfile)\" 1>&2 &\n" +" $have_nohup sh -c \"(sleep 150; rm -f $rmf $authfile)\" 1>&2 &\n" " fi\n" "\n" " t=0\n" diff --git a/x11vnc/uinput.c b/x11vnc/uinput.c index 2dfb9fe..92bd1d8 100644 --- a/x11vnc/uinput.c +++ b/x11vnc/uinput.c @@ -63,6 +63,7 @@ so, delete this exception statement from your version. int check_uinput(void); int initialize_uinput(void); +void shutdown_uinput(void); int set_uinput_accel(char *str); int set_uinput_thresh(char *str); void set_uinput_reset(int ms); @@ -83,20 +84,29 @@ static void init_key_tracker(void); static int mod_is_down(void); static int key_is_down(void); static void set_uinput_accel_xy(double fx, double fy); -static void shutdown_uinput(void); static void ptr_move(int dx, int dy); static void ptr_rel(int dx, int dy); static void button_click(int down, int btn); static int lookup_code(int keysym); static int fd = -1; -static int db = 0; +static int direct_rel_fd = -1; +static int direct_abs_fd = -1; +static int direct_btn_fd = -1; +static int direct_key_fd = -1; static int bmask = 0; +static int db = 0; static char *injectable = NULL; static char *uinput_dev = NULL; +static char *tslib_cal = NULL; +static double a[7]; static int uinput_touchscreen = 0; static int uinput_abs = 0; +static int btn_touch = 0; +static int dragskip = 0; +static int touch_always = 0; +static int touch_pressure = 1; static int abs_x = 0, abs_y = 0; static char *devs[] = { @@ -106,6 +116,13 @@ static char *devs[] = { NULL }; +#ifndef O_NDELAY +#ifdef O_NONBLOCK +#define O_NDELAY O_NONBLOCK +#else +#define O_NDELAY 0 +#endif +#endif /* * User may need to do: @@ -137,7 +154,7 @@ int check_uinput(void) { fd = -1; i = 0; while (devs[i] != NULL) { - if ( (fd = open(devs[i++], O_RDWR)) >= 0) { + if ( (fd = open(devs[i++], O_WRONLY | O_NDELAY)) >= 0) { break; } } @@ -190,39 +207,187 @@ static int key_is_down(void) { return 0; } -static void shutdown_uinput(void) { +void shutdown_uinput(void) { #ifdef UINPUT_OK - ioctl(fd, UI_DEV_DESTROY); + if (fd >= 0) { + if (db) { + rfbLog("shutdown_uinput called on fd=%d\n", fd); + } + ioctl(fd, UI_DEV_DESTROY); + close(fd); + fd = -1; + } + + /* close direct injection files too: */ + if (direct_rel_fd >= 0) close(direct_rel_fd); + if (direct_abs_fd >= 0) close(direct_abs_fd); + if (direct_btn_fd >= 0) close(direct_btn_fd); + if (direct_key_fd >= 0) close(direct_key_fd); + direct_rel_fd = -1; + direct_abs_fd = -1; + direct_btn_fd = -1; + direct_key_fd = -1; +#endif +} + +/* +grep BUS_ /usr/include/linux/input.h | awk '{print $2}' | perl -e 'while (<>) {chomp; print "#ifdef $_\n\t\tif(!strcmp(s, \"$_\"))\tudev.id.bustype = $_\n#endif\n"}' + */ +static int get_bustype(char *s) { +#ifdef UINPUT_OK + + if (!s) return 0; + +#ifdef BUS_PCI + if(!strcmp(s, "BUS_PCI")) return BUS_PCI; +#endif +#ifdef BUS_ISAPNP + if(!strcmp(s, "BUS_ISAPNP")) return BUS_ISAPNP; +#endif +#ifdef BUS_USB + if(!strcmp(s, "BUS_USB")) return BUS_USB; +#endif +#ifdef BUS_HIL + if(!strcmp(s, "BUS_HIL")) return BUS_HIL; +#endif +#ifdef BUS_BLUETOOTH + if(!strcmp(s, "BUS_BLUETOOTH")) return BUS_BLUETOOTH; +#endif +#ifdef BUS_VIRTUAL + if(!strcmp(s, "BUS_VIRTUAL")) return BUS_VIRTUAL; +#endif +#ifdef BUS_ISA + if(!strcmp(s, "BUS_ISA")) return BUS_ISA; +#endif +#ifdef BUS_I8042 + if(!strcmp(s, "BUS_I8042")) return BUS_I8042; +#endif +#ifdef BUS_XTKBD + if(!strcmp(s, "BUS_XTKBD")) return BUS_XTKBD; +#endif +#ifdef BUS_RS232 + if(!strcmp(s, "BUS_RS232")) return BUS_RS232; +#endif +#ifdef BUS_GAMEPORT + if(!strcmp(s, "BUS_GAMEPORT")) return BUS_GAMEPORT; +#endif +#ifdef BUS_PARPORT + if(!strcmp(s, "BUS_PARPORT")) return BUS_PARPORT; +#endif +#ifdef BUS_AMIGA + if(!strcmp(s, "BUS_AMIGA")) return BUS_AMIGA; #endif +#ifdef BUS_ADB + if(!strcmp(s, "BUS_ADB")) return BUS_ADB; +#endif +#ifdef BUS_I2C + if(!strcmp(s, "BUS_I2C")) return BUS_I2C; +#endif +#ifdef BUS_HOST + if(!strcmp(s, "BUS_HOST")) return BUS_HOST; +#endif +#ifdef BUS_GSC + if(!strcmp(s, "BUS_GSC")) return BUS_GSC; +#endif +#ifdef BUS_ATARI + if(!strcmp(s, "BUS_ATARI")) return BUS_ATARI; +#endif + if (atoi(s) > 0) { + return atoi(s); + } + +#endif + return 0; +} + +static void load_tslib_cal(void) { + FILE *f; + char line[1024], *p; + int i; + + /* /etc/pointercal -528 33408 -3417516 -44200 408 40292028 56541 */ + + /* this is the identity transformation: */ + a[0] = 1.0; + a[1] = 0.0; + a[2] = 0.0; + a[3] = 0.0; + a[4] = 1.0; + a[5] = 0.0; + a[6] = 1.0; + + if (tslib_cal == NULL) { + return; + } + + rfbLog("load_tslib_cal: reading %s\n", tslib_cal); + f = fopen(tslib_cal, "r"); + if (f == NULL) { + rfbLogPerror("load_tslib_cal: fopen"); + clean_up_exit(1); + } + + if (fgets(line, sizeof(line), f) == NULL) { + rfbLogPerror("load_tslib_cal: fgets"); + clean_up_exit(1); + } + fclose(f); + + p = strtok(line, " \t"); + i = 0; + while (p) { + a[i] = (double) atoi(p); + rfbLog("load_tslib_cal: a[%d] %.3f\n", i, a[i]); + p = strtok(NULL, " \t"); + i++; + if (i >= 7) { + break; + } + } + if (i != 7) { + rfbLog("load_tslib_cal: invalid tslib file format: i=%d %s\n", + i, tslib_cal); + clean_up_exit(1); + } } + int initialize_uinput(void) { #ifndef UINPUT_OK return 0; #else int i; + char *s; struct uinput_user_dev udev; if (fd >= 0) { shutdown_uinput(); - close(fd); - fd = -1; } + fd = -1; if (getenv("X11VNC_UINPUT_DEBUG")) { db = atoi(getenv("X11VNC_UINPUT_DEBUG")); rfbLog("set uinput debug to: %d\n", db); } + if (tslib_cal) { + load_tslib_cal(); + } + init_key_tracker(); if (uinput_dev) { - fd = open(uinput_dev, O_RDWR); - rfbLog("initialize_uinput: using: %s %d\n", uinput_dev, fd); + if (!strcmp(uinput_dev, "nouinput")) { + rfbLog("initialize_uinput: not creating uinput device.\n"); + return 1; + } else { + fd = open(uinput_dev, O_WRONLY | O_NDELAY); + rfbLog("initialize_uinput: using: %s %d\n", uinput_dev, fd); + } } else { i = 0; while (devs[i] != NULL) { - if ( (fd = open(devs[i], O_RDWR)) >= 0) { + if ( (fd = open(devs[i], O_WRONLY | O_NDELAY)) >= 0) { rfbLog("initialize_uinput: using: %s %d\n", devs[i], fd); break; @@ -233,15 +398,29 @@ int initialize_uinput(void) { if (fd < 0) { rfbLog("initialize_uinput: could not open an uinput device.\n"); rfbLogPerror("open"); - clean_up_exit(1); + if (direct_rel_fd < 0 && direct_abs_fd < 0 && direct_btn_fd < 0 && direct_key_fd < 0) { + clean_up_exit(1); + } + return 1; } memset(&udev, 0, sizeof(udev)); strncpy(udev.name, "x11vnc injector", UINPUT_MAX_NAME_SIZE); - udev.id.bustype = BUS_USB; /* Matters? */ - udev.id.version = 4; + s = getenv("X11VNC_UINPUT_BUS"); + if (s) { + udev.id.bustype = get_bustype(s); + } else if (0) { + udev.id.bustype = BUS_USB; + } + + s = getenv("X11VNC_UINPUT_VERSION"); + if (s) { + udev.id.version = atoi(s); + } else if (0) { + udev.id.version = 4; + } ioctl(fd, UI_SET_EVBIT, EV_REL); ioctl(fd, UI_SET_RELBIT, REL_X); @@ -249,6 +428,8 @@ int initialize_uinput(void) { ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_SYN); + for (i=0; i < 256; i++) { ioctl(fd, UI_SET_KEYBIT, i); } @@ -289,6 +470,23 @@ int initialize_uinput(void) { set_uinput_accel_xy(1.0, 1.0); } + if (db) { + rfbLog(" udev.name: %s\n", udev.name); + rfbLog(" udev.id.bustype: %d\n", udev.id.bustype); + rfbLog(" udev.id.vendor: %d\n", udev.id.vendor); + rfbLog(" udev.id.product: %d\n", udev.id.product); + rfbLog(" udev.id.version: %d\n", udev.id.version); + rfbLog(" udev.ff_effects_max: %d\n", udev.ff_effects_max); + rfbLog(" udev.absmin[ABS_X]: %d\n", udev.absmin[ABS_X]); + rfbLog(" udev.absmax[ABS_X]: %d\n", udev.absmax[ABS_X]); + rfbLog(" udev.absfuzz[ABS_X]: %d\n", udev.absfuzz[ABS_X]); + rfbLog(" udev.absflat[ABS_X]: %d\n", udev.absflat[ABS_X]); + rfbLog(" udev.absmin[ABS_Y]: %d\n", udev.absmin[ABS_Y]); + rfbLog(" udev.absmax[ABS_Y]: %d\n", udev.absmax[ABS_Y]); + rfbLog(" udev.absfuzz[ABS_Y]: %d\n", udev.absfuzz[ABS_Y]); + rfbLog(" udev.absflat[ABS_Y]: %d\n", udev.absflat[ABS_Y]); + } + write(fd, &udev, sizeof(udev)); if (ioctl(fd, UI_DEV_CREATE) != 0) { @@ -408,6 +606,11 @@ void parse_uinput_str(char *in) { uinput_abs = 0; abs_x = abs_y = 0; + if (tslib_cal) { + free(tslib_cal); + tslib_cal = NULL; + } + p = strtok(str, ","); while (p) { if (p[0] == '/') { @@ -415,6 +618,11 @@ void parse_uinput_str(char *in) { free(uinput_dev); } uinput_dev = strdup(p); + } else if (strstr(p, "nouinput") == p) { + if (uinput_dev) { + free(uinput_dev); + } + uinput_dev = strdup(p); } else if (strstr(p, "accel=") == p) { q = p + strlen("accel="); if (! set_uinput_accel(q)) { @@ -435,6 +643,12 @@ void parse_uinput_str(char *in) { free(injectable); } injectable = strdup(p); + } else if (strstr(p, "touch_always=") == p) { + touch_always = atoi(p + strlen("touch_always=")); + } else if (strstr(p, "btn_touch=") == p) { + btn_touch = atoi(p + strlen("btn_touch=")); + } else if (strstr(p, "dragskip=") == p) { + dragskip = atoi(p + strlen("dragskip=")); } else if (strstr(p, "touch") == p) { int gw, gh; q = strchr(p, '='); @@ -452,7 +666,38 @@ void parse_uinput_str(char *in) { abs_x = gw; abs_y = gh; } - + } else if (strstr(p, "pressure=") == p) { + touch_pressure = atoi(p + strlen("pressure=")); + } else if (strstr(p, "direct_rel=") == p) { + direct_rel_fd = open(p+strlen("direct_rel="), O_WRONLY); + if (direct_rel_fd < 0) { + rfbLogPerror("uinput: direct_rel open"); + } else { + rfbLog("uinput: opened: %s fd=%d\n", p, direct_rel_fd); + } + } else if (strstr(p, "direct_abs=") == p) { + direct_abs_fd = open(p+strlen("direct_abs="), O_WRONLY); + if (direct_abs_fd < 0) { + rfbLogPerror("uinput: direct_abs open"); + } else { + rfbLog("uinput: opened: %s fd=%d\n", p, direct_abs_fd); + } + } else if (strstr(p, "direct_btn=") == p) { + direct_btn_fd = open(p+strlen("direct_btn="), O_WRONLY); + if (direct_btn_fd < 0) { + rfbLogPerror("uinput: direct_btn open"); + } else { + rfbLog("uinput: opened: %s fd=%d\n", p, direct_btn_fd); + } + } else if (strstr(p, "direct_key=") == p) { + direct_key_fd = open(p+strlen("direct_key="), O_WRONLY); + if (direct_key_fd < 0) { + rfbLogPerror("uinput: direct_key open"); + } else { + rfbLog("uinput: opened: %s fd=%d\n", p, direct_key_fd); + } + } else if (strstr(p, "tslib_cal=") == p) { + tslib_cal = strdup(p+strlen("tslib_cal=")); } else { rfbLog("invalid UINPUT option: %s\n", p); clean_up_exit(1); @@ -465,6 +710,7 @@ void parse_uinput_str(char *in) { static void ptr_move(int dx, int dy) { #ifdef UINPUT_OK struct input_event ev; + int d = direct_rel_fd < 0 ? fd : direct_rel_fd; if (injectable && strchr(injectable, 'M') == NULL) { return; @@ -472,29 +718,45 @@ static void ptr_move(int dx, int dy) { memset(&ev, 0, sizeof(ev)); + if (db) fprintf(stderr, "ptr_move(%d, %d) fd=%d\n", dx, dy, d); + gettimeofday(&ev.time, NULL); ev.type = EV_REL; ev.code = REL_Y; ev.value = dy; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); ev.type = EV_REL; ev.code = REL_X; ev.value = dx; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); #else if (!dx || !dy) {} #endif } -static void ptr_abs(int x, int y) { +static void apply_tslib(int *x, int *y) { + double x1 = *x, y1 = *y, x2, y2; + + /* this is the inverse of the tslib linear transform: */ + x2 = (a[4] * (a[6] * x1 - a[2]) - a[1] * (a[6] * y1 - a[5]))/(a[4]*a[0] - a[1]*a[3]); + y2 = (a[0] * (a[6] * y1 - a[5]) - a[3] * (a[6] * x1 - a[2]))/(a[4]*a[0] - a[1]*a[3]); + + *x = (int) x2; + *y = (int) y2; +} + + +static void ptr_abs(int x, int y, int p) { #ifdef UINPUT_OK struct input_event ev; + int x0, y0; + int d = direct_abs_fd < 0 ? fd : direct_abs_fd; if (injectable && strchr(injectable, 'M') == NULL) { return; @@ -502,23 +764,37 @@ static void ptr_abs(int x, int y) { memset(&ev, 0, sizeof(ev)); - if (db) fprintf(stderr, "ptr_abs(%d, %d)\n", x, y); + x0 = x; + y0 = y; + + if (tslib_cal) { + apply_tslib(&x, &y); + } + + if (db) fprintf(stderr, "ptr_abs(%d, %d => %d %d, p=%d) fd=%d\n", x0, y0, x, y, p, d); gettimeofday(&ev.time, NULL); ev.type = EV_ABS; ev.code = ABS_Y; ev.value = y; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); ev.type = EV_ABS; ev.code = ABS_X; ev.value = x; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); + + if (p >= 0) { + ev.type = EV_ABS; + ev.code = ABS_PRESSURE; + ev.value = p; + write(d, &ev, sizeof(ev)); + } ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); #else if (!x || !y) {} #endif @@ -658,7 +934,7 @@ static void ptr_rel(int dx, int dy) { resid_y -= dyf; if (db > 1) fprintf(stderr, "*%s resid: dx dy: %d %d %f %f\n", accel > 1 ? "*" : " ", dxf, dyf, resid_x, resid_y); -if (0) {usleep(100*1000)}; +if (0) {usleep(100*1000) ;} ptr_move(dxf, dyf); } } @@ -667,12 +943,13 @@ if (0) {usleep(100*1000)}; static void button_click(int down, int btn) { #ifdef UINPUT_OK struct input_event ev; + int d = direct_btn_fd < 0 ? fd : direct_btn_fd; if (injectable && strchr(injectable, 'B') == NULL) { return; } - if (db) fprintf(stderr, "button_click: btn %d %s\n", btn, down ? "down" : "up"); + if (db) fprintf(stderr, "button_click: btn %d %s fd=%d\n", btn, down ? "down" : "up", d); memset(&ev, 0, sizeof(ev)); gettimeofday(&ev.time, NULL); @@ -696,12 +973,12 @@ static void button_click(int down, int btn) { return; } - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); last_button_click = dnow(); #else @@ -756,15 +1033,6 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) { do_reset = 1; } if (uinput_abs) { -#if 0 - /* this is a bad idea... need to do something else */ - if (do_reset) { - ptr_abs(dpy_x, dpy_y); - usleep(10*1000); - ptr_abs(x, y); - usleep(10*1000); - } -#endif do_reset = 0; } @@ -849,7 +1117,7 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) { } else { ptr_rel(x, y); } - if (1) {usleep(10*1000)}; + if (1) {usleep(10*1000) ;} last_x = x; last_y = y; @@ -863,8 +1131,10 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) { if (input.motion) { if (x != last_x || y != last_y) { - if (uinput_abs) { - ptr_abs(x, y); + if (uinput_touchscreen) { + ; + } else if (uinput_abs) { + ptr_abs(x, y, -1); } else { ptr_rel(x - last_x, y - last_y); } @@ -888,7 +1158,46 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) { fprintf(stderr, "button_mask: %s\n", bitprint(button_mask, 16)); } - if (mask != last_mask) { + if (uinput_touchscreen) { + if (!btn_touch) { + static int down_count = 0; + int p = touch_pressure >=0 ? touch_pressure : 0; + if (!last_mask && !mask) { + if (touch_always) { + ptr_abs(last_x, last_y, 0); + } + } else if (!last_mask && mask) { + ptr_abs(last_x, last_y, p); + down_count = 0; + } else if (last_mask && !mask) { + ptr_abs(last_x, last_y, 0); + } else if (last_mask && mask) { + down_count++; + if (dragskip > 0) { + if (down_count % dragskip == 0) { + ptr_abs(last_x, last_y, p); + } + } else { + ptr_abs(last_x, last_y, p); + } + } + } else { + if (!last_mask && !mask) { + if (touch_always) { + ptr_abs(last_x, last_y, 0); + } + } else if (!last_mask && mask) { + ptr_abs(last_x, last_y, 0); + button_click(1, 0); + } else if (last_mask && !mask) { + ptr_abs(last_x, last_y, 0); + button_click(0, 0); + } else if (last_mask && mask) { + ; + } + } + last_mask = mask; + } else if (mask != last_mask) { int i; for (i=1; i <= MAX_BUTTONS; i++) { int down, b = 1 << (i-1); @@ -902,6 +1211,9 @@ void uinput_pointer_command(int mask, int x, int y, rfbClientPtr client) { } button_click(down, i); } + if (mask && uinput_abs && touch_pressure >= 0) { + ptr_abs(last_x, last_y, touch_pressure); + } last_mask = mask; } bmask = mask; @@ -912,6 +1224,7 @@ void uinput_key_command(int down, int keysym, rfbClientPtr client) { struct input_event ev; int scancode; allowed_input_t input; + int d = direct_key_fd < 0 ? fd : direct_key_fd; if (injectable && strchr(injectable, 'K') == NULL) { return; @@ -929,7 +1242,7 @@ void uinput_key_command(int down, int keysym, rfbClientPtr client) { if (scancode < 0) { return; } - if (db) fprintf(stderr, "uinput_key_command: %d -> %d %s\n", keysym, scancode, down ? "down" : "up"); + if (db) fprintf(stderr, "uinput_key_command: %d -> %d %s fd=%d\n", keysym, scancode, down ? "down" : "up", d); memset(&ev, 0, sizeof(ev)); gettimeofday(&ev.time, NULL); @@ -937,12 +1250,12 @@ void uinput_key_command(int down, int keysym, rfbClientPtr client) { ev.code = (unsigned char) scancode; ev.value = down; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); ev.type = EV_SYN; ev.code = SYN_REPORT; ev.value = 0; - write(fd, &ev, sizeof(ev)); + write(d, &ev, sizeof(ev)); if (0 <= scancode && scancode < 256) { key_pressed[scancode] = down ? 1 : 0; @@ -952,6 +1265,10 @@ void uinput_key_command(int down, int keysym, rfbClientPtr client) { #endif } +#if 0 + grep 'case XK_' x0vnc.c | sed -e 's/case /$key_lookup{/' -e 's/:/}/' -e 's/return /= $/' +#endif + static int lookup_code(int keysym) { if (keysym == NoSymbol) { diff --git a/x11vnc/uinput.h b/x11vnc/uinput.h index 01e8708..346e97c 100644 --- a/x11vnc/uinput.h +++ b/x11vnc/uinput.h @@ -37,6 +37,7 @@ so, delete this exception statement from your version. extern int check_uinput(void); extern int initialize_uinput(void); +extern void shutdown_uinput(void); extern int set_uinput_accel(char *str); extern int set_uinput_thresh(char *str); extern void set_uinput_reset(int ms); diff --git a/x11vnc/unixpw.c b/x11vnc/unixpw.c index b610fa9..ccdb195 100644 --- a/x11vnc/unixpw.c +++ b/x11vnc/unixpw.c @@ -565,6 +565,12 @@ char *get_pty_ptmx(int *fd_p) { ioctl(fd, TIOCFLUSH, (char *) 0); #endif + if (strlen(slave) > sizeof(slave_str)/2) { + rfbLog("get_pty_ptmx: slave string length too long.\n"); + close(fd); + return NULL; + } + strcpy(slave_str, slave); *fd_p = fd; return slave_str; @@ -1743,7 +1749,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { down ? "down":"up ", keysym, keystr); } - if (keysym == XK_Return || keysym == XK_Linefeed) { + if (keysym == XK_Return || keysym == XK_Linefeed || keysym == XK_Tab) { /* let "up" pass down below for Return case */ if (down) { return; @@ -1866,7 +1872,7 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) { return; } - if (keysym == XK_Return || keysym == XK_Linefeed) { + if (keysym == XK_Return || keysym == XK_Linefeed || keysym == XK_Tab) { char pw[] = "Password: "; if (down) { diff --git a/x11vnc/user.c b/x11vnc/user.c index e9028ba..f09fbb9 100644 --- a/x11vnc/user.c +++ b/x11vnc/user.c @@ -2769,6 +2769,7 @@ if (db) fprintf(stderr, "\n"); clean_up_exit(1); } n = fread(line2, 1, 16384, p); + pclose(p); } if (tmp_fd >= 0) { unlink(tmp); diff --git a/x11vnc/util.h b/x11vnc/util.h index 64c9f76..55585cf 100644 --- a/x11vnc/util.h +++ b/x11vnc/util.h @@ -96,8 +96,8 @@ extern struct timeval _mysleep; ((KeySym)(keysym) != XK_Caps_Lock) && ((KeySym)(keysym) != XK_Shift_Lock))) /* - * Not sure why... but when threaded we have to mutex our X11 calls to - * avoid XIO crashes. + * When threaded we have to mutex our X11 calls to avoid XIO crashes + * due to callbacks. */ #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD extern MUTEX(x11Mutex); diff --git a/x11vnc/v4l.c b/x11vnc/v4l.c index 84bfd08..86c33a6 100644 --- a/x11vnc/v4l.c +++ b/x11vnc/v4l.c @@ -434,23 +434,23 @@ static void apply_settings(char *dev, char *settings, int *fd) { static double dval = 0.05; static int v4l1_dpct(int old, int d) { - int new, max = V4L1_MAX; + int newval, max = V4L1_MAX; /* -1 and 1 are special cases for "small increments" */ if (d == -1) { - new = old - (int) (dval * max); + newval = old - (int) (dval * max); } else if (d == 1) { - new = old + (int) (dval * max); + newval = old + (int) (dval * max); } else { - new = (d * max)/100; + newval = (d * max)/100; } - if (new < 0) { - new = 0; + if (newval < 0) { + newval = 0; } - if (new > max) { - new = max; + if (newval > max) { + newval = max; } - return new; + return newval; } static void v4l_requery(void) { diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index cfab152..8a92433 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -1,8 +1,8 @@ .\" This file was automatically generated from x11vnc -help output. -.TH X11VNC "1" "September 2010" "x11vnc " "User Commands" +.TH X11VNC "1" "December 2010" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.9.13, lastmod: 2010-09-10 + version: 0.9.13, lastmod: 2010-12-20 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -925,6 +925,11 @@ server with them, grabbing the keyboard himself, etc. Some degree of cooperation from the person at the display is assumed. This is intended for remote help-desk or educational usage modes. +.IP +Note: on some recent (12/2010) X servers and/or +desktops, \fB-grabkbd\fR no longer works: it prevents the +window manager from resizing windows and similar things. +Try \fB-ungrabboth\fR below (might not work.) .PP \fB-grabptr\fR .IP @@ -940,6 +945,13 @@ for resizes, etc, will act on the local user's input. Again, some degree of cooperation from the person at the display is assumed. .PP +\fB-ungrabboth\fR +.IP +Whenever there is any input (either keyboard or +pointer), ungrab *both* the keyboard and the pointer +while injecting the synthetic input. This is to allow +window managers, etc. a chance to grab. +.PP \fB-grabalways\fR .IP Apply both \fB-grabkbd\fR and \fB-grabptr\fR even when no VNC @@ -1569,6 +1581,15 @@ xauthority data for the display. For example; .IP xauth extract - $DISPLAY" .IP +NOTE: As specified in the previous paragraph, you can +supply your own WAIT:cmd=... program or script, BUT +there are two very useful *BUILT-IN* ones: FINDDISPLAY +(alias \fB-find\fR above) and FINDCREATEDISPLAY (alias \fB-create\fR +above.) Most people use these instead of creating +their own script. Read the following (especially the +BUILT-IN modes sections) to see how to configure these +two useful builtin \fB-display\fR WAIT: modes. +.IP In the case of \fB-unixpw\fR (and \fB-unixpw_nis\fR only if x11vnc is running as root), then the cmd= command is run as the user who just authenticated via the login and @@ -1600,6 +1621,11 @@ type and enter your password incorrectly, to retrieve your long "login:" line press the Up arrow once (before typing anything else). .IP +Most of these colon options only apply to the builtin +FINDDISPLAY and FINDCREATEDISPLAY modes, but note +that they are passed to the extrenal command in the +environment as well and so could be used. +.IP In the login panel, press F1 to get a list of the available options that you can add after the username. .IP @@ -1633,23 +1659,19 @@ prompt. For example \fB-env\fR FD_USERPREFS=.x11vnc_create and the user put "geom=1600x1200" in his ~/.x11vnc_create file. .IP -To troubleshoot the FINDCREATEDISPLAY mechanism, -set the following env. var. to an output log file, -e.g \fB-env\fR CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt -.IP To disable the option setting set the environment variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc. To set any other options, the user can use the gui (x11vnc \fB-gui\fR connect) or the remote control method (x11vnc \fB-R\fR opt:val) during his VNC session. .IP -The combination of \fB-display\fR WAIT:cmd=... and \fB-unixpw\fR -allows automatic pairing of an unix authenticated VNC -user with his desktop. This could be very useful on -SunRays and also any system where multiple users share -a given machine. The user does not need to remember -special ports or passwords set up for his desktop -and VNC. +So we see the combination of \fB-display\fR WAIT:cmd=... and +\fB-unixpw\fR allows automatic pairing of an unix +authenticated VNC user with his desktop. This could +be very useful on SunRays and also any system where +multiple users share a given machine. The user does +not need to remember special ports or passwords set up +for his desktop and VNC. .IP A nice way to use WAIT:cmd=... is out of .IR inetd (8) @@ -1662,7 +1684,9 @@ the user as well. Note: there will be a 2nd SSL helper process that will not switch, but it is only encoding and decoding the encrypted stream at that point. .IP -Automatic Finding of User X Sessions: +BUILT-IN modes: +.IP +\fB--\fR Automatic Finding of User X Sessions \fB--\fR .IP As a special case, WAIT:cmd=FINDDISPLAY will run a script that works on most Unixes to determine a user's @@ -1670,7 +1694,7 @@ DISPLAY variable and xauthority data (see .IR who (1) ). .IP -The option "\fB-find\fR" is an alias for this mode. +NOTE: The option "\fB-find\fR" is an alias for this mode. .IP To have this default script printed to stdout (e.g. for customization) run with WAIT:cmd=FINDDISPLAY-print To @@ -1715,7 +1739,14 @@ using "+" instead of "," If "nd=all" or you set X11VNC_SKIP_DISPLAY=all then all display finding fails as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) .IP -Automatic Creation of User X Sessions: +On some systems +.IR lsof (1) +can be very slow. Set the +env. var. FIND_DISPLAY_NO_LSOF=1 to skip using lsof to +try to find the Linux VT the X server is running on. +set FIND_DISPLAY_NO_VT_FIND=1 to avoid looking at all. +.IP +\fB--\fR Automatic Creation of User X Sessions \fB--\fR .IP An interesting option is WAIT:cmd=FINDCREATEDISPLAY that is like FINDDISPLAY in that is uses the same method @@ -1724,13 +1755,19 @@ find one it will try to *start* up an X server session for the user. This is the only time x11vnc tries to actually start up an X server. .IP -The option "\fB-create\fR" is an alias for this mode. +NOTE: The option "\fB-create\fR" is an alias for this mode. .IP It will start looking for an open display number at :20 Override via X11VNC_CREATE_STARTING_DISPLAY_NUMBER=n By default 80 X displays are allowed (i.e. going to :99) Override via X11VNC_CREATE_MAX_DISPLAYS=n .IP +For its heuristics, the create display script sets +LC_ALL=C so that command output is uniform. By default +it will try to restore LC_ALL right before starting the +user session. However, if you don't mind it keeping +LC_ALL=C set the env. var.: X11VNC_CREATE_LC_ALL_C_OK=1 +.IP By default FINDCREATEDISPLAY will try Xvfb and then Xdummy: .IP @@ -1757,6 +1794,10 @@ The user must exit the X session in the usual way for it to terminate (or kill the X server process if all else fails). .IP +To troubleshoot the FINDCREATEDISPLAY mechanism, +set the following env. var. to an output log file, +e.g \fB-env\fR CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt +.IP So this is a somewhat odd mode for x11vnc in that it will start up and poll virtual X servers! This can be used from, say, @@ -4614,6 +4655,7 @@ Default: take naps Time in seconds after NO activity (e.g. screen blank) to really throttle down the screen polls (i.e. sleep for about 1.5 secs). Use 0 to disable. Default: 60 +Set the env. var. X11VNC_SB_FACTOR to scale it. .PP \fB-readtimeout\fR \fIn\fR .IP @@ -5129,18 +5171,19 @@ do not prefer the default 16bpp set RAWFB_VCSA_BPP to using the 'console_guess' string printed at startup, be sure to indicate the snap: method. .IP -uinput: If the Linux version appears to be 2.6 or -later and the "uinput" module appears to be present -(modprobe uinput), then the uinput method will be used -instead of /dev/ttyN. uinput allows insertion of BOTH -keystrokes and mouse input and so it preferred when -accessing graphical (e.g. QT-embedded) linux console -apps. See \fB-pipeinput\fR UINPUT below for more information -on this mode; you will have to use \fB-pipeinput\fR if you -want to tweak any UINPUT parameters. You may also want -to also use the \fB-nodragging\fR and \fB-cursor\fR none options. -Use "console0", etc or \fB-pipeinput\fR CONSOLE to force -the /dev/ttyN method. +uinput: If the Linux version appears to be 2.6 +or later and the "uinput" module appears to be +present (modprobe uinput), then the uinput method +will be used instead of /dev/ttyN. uinput allows +insertion of BOTH keystrokes and mouse input and so it +preferred when accessing graphical (e.g. QT-embedded) +linux console apps. It also provides more accurate +keystroke insertion. See \fB-pipeinput\fR UINPUT below for +more information on this mode; you will have to use +\fB-pipeinput\fR if you want to tweak any UINPUT parameters. +You may also want to also use the \fB-nodragging\fR and +\fB-cursor\fR none options. Use "console0", etc or +\fB-pipeinput\fR CONSOLE to force the /dev/ttyN method. .IP Note you can change the Linux VT remotely using the .IR chvt (1) @@ -5181,7 +5224,11 @@ This mode is really only of use if you are trying to improve performance in the case of many (e.g. > 10) simultaneous VNC viewers, and you try a divide and conquer scheme to reduce bandwidth and improve -responsiveness. +responsiveness. (However, another user found this mode +useful to export a demo display through a slow link: +then multiple demo viewers connected to the reflecting +x11vnc on the fast side of the link, and so avoided +all of the demo viewers going through the slow link.) .IP For example, if there will be 64 simultaneous VNC viewers this can lead to a lot of redundant VNC traffic @@ -5212,6 +5259,13 @@ the password needed to log into the vnc host server, or to "file:path_to_file" to indicate a file containing the password as its first line. .IP +To set the pixel format that x11vnc requests as a VNC +CLIENT set the env. vars: X11VNC_REFLECT_bitsPerSample +X11VNC_REFLECT_samplesPerPixel, and +X11VNC_REFLECT_bytesPerPixel; the defaults are 8, 3, 4. +2, 3, 1 would give a low color mode. See the function +rfbGetClient() in libvncclient for more info. +.IP The VNC HOST mode implies \fB-shared.\fR Use \fB-noshared\fR as a subsequent cmdline option to disable sharing. .PP @@ -5278,7 +5332,8 @@ and insert the module with "modprobe uinput". .IP The UINPUT mode currently only does US keyboards (a scan code option may be added), and not all keysyms -are supported. +are supported. But it is probably more accurate than +the "CONSOLE" method. .IP You may want to use the options \fB-cursor\fR none and \fB-nodragging\fR in this mode. @@ -5320,16 +5375,6 @@ in 1 jump), This correction seems to be needed but can cause jerkiness or unexpected behavior with menus, etc. Use reset=0 to disable. .IP -If the uinput device has an absolute pointer (as opposed -to a normal mouse that is a relative pointer) you can -specify the option "abs". Note that a touchpad -on a laptop is an absolute device to some degree. -This (usually) avoids all the problems with mouse -acceleration. If x11vnc has trouble deducing the size -of the device, use "abs=WxH". Furthermore, if the -device is a touchscreen (assumed to have an absolute -pointer) use "touch" or "touch=WxH". -.IP If you set the env. var X11VNC_UINPUT_THRESHOLDS then the thresh=n mode will be enabled. It is currently not working well. If |dx| <= thresh and |dy| < thresh @@ -5339,8 +5384,70 @@ no acceleration is applied. Use "thresh=+n" |dx| + Example: \fB-pipeinput\fR UINPUT:accel=4.0 \fB-cursor\fR none .IP -You can also set the env. var X11VNC_UINPUT_DEBUG=1 or -higher to get debugging output for UINPUT mode. +If the uinput device has an absolute pointer (as opposed +to a normal mouse that is a relative pointer) you can +specify the option "abs". Note that a touchpad +on a laptop is an absolute device to some degree. +This (usually) avoids all the problems with mouse +acceleration. If x11vnc has trouble deducing the +size of the device, use "abs=WxH". Furthermore, +if the device is a touchscreen (assumed to have an +absolute pointer) use "touch" or "touch=WxH". +For touchscreens, when a mouse button is pressed, +a pressure increase is injected, and when the button +is released a pressure of zero is injected. +.IP +If touch has been set, use "touch_always=1" to +indicate whenever the mouse moves with no button +pressed, a touch event of zero pressure should be +sent anyway. Also use "btn_touch=1" to indicate a +BTN_TOUCH keystroke press or release should be sent +instead of a pressure change. Set "dragskip=n" to +skip n dragged mouse touches (with pressure applied) +before injecting one. To indicate the pressure that +should be sent when there is a button click for a +touchscreen device, specify pressure=n, e.g. n=5. The +default is n=1. +.IP +If a touch screen is being used ("touch" above) +and it is having its input processed by tslib, you can +specify the tslib calibration file via tslib_cal=. +For example, tslib_cal=/etc/pointercal. To get accurate +or even usable positioning this is required when tslib +is in use. +.IP +The Linux uinput mechanism can be bypassed and one can +write input events DIRECTLY to the devices instead. +To do this, specify one or more of the following +for the input classes: direct_rel= +direct_abs= direct_btn= or +direct_key=. The file is usually +something like /dev/input/event1 but you can specify +any device file or pipe. You must specify each one +of the above classes even if they correspond to the +same device file (rel/abs and btn are often the same.) +Look at the file /proc/bus/input/devices to get an idea +what is available and the device filenames. Note: +The /dev/input/mouse* devices do not seem to work, +use the corresponding /dev/input/event* file instead. +Any input class not directly specified as above will be +handled via the uinput mechanism. To disable creating a +uinput device (and thereby discarding unhandled input), +specify "nouinput". +.IP +Examples: +.IP +\fB-pipeinput\fR UINPUT:direct_abs=/dev/input/event1 +.IP +this was used on a qtmoko Neo freerunner (armel): +.IP +\fB-pipeinput\fR UINPUT:touch,tslib_cal=/etc/pointercal, +direct_abs=/dev/input/event1,nouinput,dragskip=4 +.IP +(where the long line has been split into two.) +.IP +You can set the env. var X11VNC_UINPUT_DEBUG=1 or higher +to get debugging output for UINPUT mode. .PP \fB-macnodim\fR .IP diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 3f965e2..d427f32 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -1065,6 +1065,7 @@ static void check_rcfile(int argc, char **argv) { if (! home) { norc = 1; } else { + memset(rcfile, 0, sizeof(rcfile)); strncpy(rcfile, home, 500); free(home); @@ -1394,6 +1395,7 @@ static void quick_pw(char *str) { if(fgets(tmp, 1024, in) == NULL) { exit(2); } + fclose(in); q = strdup(tmp); } else { q = strdup(str+1); @@ -2574,6 +2576,10 @@ int main(int argc, char* argv[]) { grab_ptr = 1; continue; } + if (!strcmp(arg, "-ungrabboth")) { + ungrab_both = 1; + continue; + } if (!strcmp(arg, "-grabalways")) { grab_kbd = 1; grab_ptr = 1; @@ -4274,7 +4280,7 @@ int main(int argc, char* argv[]) { char *pstr = "%VNCDISPLAY"; if (strstr(logfile, pstr)) { char *h = this_host(); - char *s, *q, *new; + char *s, *q, *newlog; int n, p = got_rfbport_val; /* we don't really know the port yet... so guess */ if (p < 0) { @@ -4293,23 +4299,23 @@ int main(int argc, char* argv[]) { n++; q = t+1; } - new = (char *) malloc(strlen(logfile) + n * strlen(pstr)); - new[0] = '\0'; + newlog = (char *) malloc(strlen(logfile) + n * strlen(pstr)); + newlog[0] = '\0'; q = logfile; while (1) { char *t = strstr(q, pstr); if (!t) { - strcat(new, q); + strcat(newlog, q); break; } - strncat(new, q, t - q); - strcat(new, s); + strncat(newlog, q, t - q); + strcat(newlog, s); q = t + strlen(pstr); } - logfile = new; + logfile = newlog; if (!quiet && !got_inetd) { - rfbLog("Expanded logfile to '%s'\n", new); + rfbLog("Expanded logfile to '%s'\n", newlog); } free(s); @@ -4317,7 +4323,7 @@ int main(int argc, char* argv[]) { pstr = "%HOME"; if (strstr(logfile, pstr)) { char *h = get_home_dir(); - char *s, *q, *new; + char *s, *q, *newlog; s = (char *) malloc(strlen(h) + 32); sprintf(s, "%s", h); @@ -4329,23 +4335,23 @@ int main(int argc, char* argv[]) { n++; q = t+1; } - new = (char *) malloc(strlen(logfile) + n * strlen(pstr)); - new[0] = '\0'; + newlog = (char *) malloc(strlen(logfile) + n * strlen(pstr)); + newlog[0] = '\0'; q = logfile; while (1) { char *t = strstr(q, pstr); if (!t) { - strcat(new, q); + strcat(newlog, q); break; } - strncat(new, q, t - q); - strcat(new, s); + strncat(newlog, q, t - q); + strcat(newlog, s); q = t + strlen(pstr); } - logfile = new; + logfile = newlog; if (!quiet && !got_inetd) { - rfbLog("Expanded logfile to '%s'\n", new); + rfbLog("Expanded logfile to '%s'\n", newlog); } free(s); } diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h index 8d69543..3299109 100644 --- a/x11vnc/x11vnc.h +++ b/x11vnc/x11vnc.h @@ -133,6 +133,8 @@ so, delete this exception statement from your version. * -DPOLL_8TO24_DELAY=N * -DDEBUG_XEVENTS=1 enable printout for X events. * + * -DX11VNC_MACOSX_USE_GETMAINDEVICE use deprecated GetMainDevice on macosx + * * Set these in CPPFLAGS before running configure. E.g.: * * % env CPPFLAGS="-DFOREVER -DREMOTE_CONTROL=0" ./configure diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index fc6215b..ae048ee 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.9.13 lastmod: 2010-09-10"; +char lastmod[] = "0.9.13 lastmod: 2010-12-20"; /* X display info */ diff --git a/x11vnc/xevents.c b/x11vnc/xevents.c index 2fc122d..72b6515 100644 --- a/x11vnc/xevents.c +++ b/x11vnc/xevents.c @@ -57,6 +57,7 @@ int grab_buster = 0; int grab_kbd = 0; int grab_ptr = 0; int grab_always = 0; +int ungrab_both = 0; int grab_local = 0; int sync_tod_delay = 20; diff --git a/x11vnc/xevents.h b/x11vnc/xevents.h index dbdddde..5b8bdce 100644 --- a/x11vnc/xevents.h +++ b/x11vnc/xevents.h @@ -39,6 +39,7 @@ extern int grab_buster; extern int grab_kbd; extern int grab_ptr; extern int grab_always; +extern int ungrab_both; extern int grab_local; extern int sync_tod_delay; diff --git a/x11vnc/xrecord.c b/x11vnc/xrecord.c index 4f79dce..87e15b9 100644 --- a/x11vnc/xrecord.c +++ b/x11vnc/xrecord.c @@ -73,7 +73,7 @@ void initialize_xrecord(void); void zerodisp_xrecord(void); void shutdown_xrecord(void); int xrecord_skip_keysym(rfbKeySym keysym); -int xrecord_skip_button(int new, int old); +int xrecord_skip_button(int newb, int old); int xrecord_scroll_keysym(rfbKeySym keysym); void check_xrecord_reset(int force); void xrecord_watch(int start, int setby); @@ -410,9 +410,9 @@ int xrecord_skip_keysym(rfbKeySym keysym) { return 0; } -int xrecord_skip_button(int new, int old) { +int xrecord_skip_button(int new_button, int old) { /* unused vars warning: */ - if (new || old) {} + if (new_button || old) {} return 0; } diff --git a/x11vnc/xrecord.h b/x11vnc/xrecord.h index cee660d..2c1e2d7 100644 --- a/x11vnc/xrecord.h +++ b/x11vnc/xrecord.h @@ -60,7 +60,7 @@ extern void initialize_xrecord(void); extern void zerodisp_xrecord(void); extern void shutdown_xrecord(void); extern int xrecord_skip_keysym(rfbKeySym keysym); -extern int xrecord_skip_button(int new, int old); +extern int xrecord_skip_button(int newb, int old); extern int xrecord_scroll_keysym(rfbKeySym keysym); extern void check_xrecord_reset(int force); extern void xrecord_watch(int start, int setby); diff --git a/x11vnc/xwrappers.c b/x11vnc/xwrappers.c index 667957e..bb73565 100644 --- a/x11vnc/xwrappers.c +++ b/x11vnc/xwrappers.c @@ -347,7 +347,15 @@ XImage *XCreateImage_wr(Display *disp, Visual *visual, unsigned int depth, xi = (XImage *) malloc(sizeof(XImage)); memset(xi, 0, sizeof(XImage)); xi->depth = depth; - xi->bits_per_pixel = (depth == 24) ? 32 : depth; + if (depth >= 24) { + xi->bits_per_pixel = 32; + } else if (depth > 16) { + xi->bits_per_pixel = 24; + } else if (depth > 8) { + xi->bits_per_pixel = 16; + } else { + xi->bits_per_pixel = 8; + } xi->format = format; xi->xoffset = offset; xi->data = data; @@ -706,7 +714,7 @@ void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h) { src = snap->data + snap->bytes_per_line*y + pixelsize*x; dst = dest->data; -if (db) fprintf(stderr, "snap->bytes_per_line: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d\n", snap->bytes_per_line, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x); +if (db) fprintf(stderr, "snap->bytes_per_line: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", snap->bytes_per_line, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize); for (line = 0; line < h; line++) { memcpy(dst, src, w * pixelsize); @@ -725,7 +733,7 @@ if (db) fprintf(stderr, "snap->bytes_per_line: %d, dest->bytes_per_line: %d, w: src = raw_fb_addr + raw_fb_offset + bpl*y + pixelsize*x; dst = dest->data; -if (db) fprintf(stderr, "bpl: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d\n", bpl, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x); +if (db) fprintf(stderr, "bpl: %d, dest->bytes_per_line: %d, w: %d h: %d dpy_x: %d wdpy_x: %d cdpy_x: %d bpp: %d pixelsize: %d\n", bpl, dest->bytes_per_line, w, h, dpy_x, wdpy_x, cdpy_x, bpp, pixelsize); for (line = 0; line < h; line++) { memcpy(dst, src, w * pixelsize); @@ -878,6 +886,7 @@ void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, unsigned long delay) { static int first = 1; + int regrab = 0; RAWFB_RET_VOID @@ -903,11 +912,16 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, if (grab_kbd) { XUngrabKeyboard(dpy, CurrentTime); + regrab = 1; + } + if (grab_ptr && ungrab_both) { + XUngrabPointer(dpy, CurrentTime); + regrab = 1; } if (xtrap_input) { XTRAP_FakeKeyEvent_wr(dpy, key, down, delay); - if (grab_kbd) { + if (regrab) { adjust_grabs(1, 1); } return; @@ -923,7 +937,7 @@ void XTestFakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down, } #if LIBVNCSERVER_HAVE_XTEST XTestFakeKeyEvent(dpy, key, down, delay); - if (grab_kbd) { + if (regrab) { adjust_grabs(1, 1); } if (debug_keyboard) { @@ -964,6 +978,7 @@ void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, unsigned long delay) { + int regrab = 0; RAWFB_RET_VOID #if NO_X11 @@ -974,11 +989,16 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, if (grab_ptr) { XUngrabPointer(dpy, CurrentTime); + regrab = 1; + } + if (grab_kbd && ungrab_both) { + XUngrabKeyboard(dpy, CurrentTime); + regrab = 1; } if (xtrap_input) { XTRAP_FakeButtonEvent_wr(dpy, button, is_press, delay); - if (grab_ptr) { + if (regrab) { adjust_grabs(1, 1); } return; @@ -995,7 +1015,7 @@ void XTestFakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press, #if LIBVNCSERVER_HAVE_XTEST XTestFakeButtonEvent(dpy, button, is_press, delay); #endif - if (grab_ptr) { + if (regrab) { adjust_grabs(1, 1); } #endif /* NO_X11 */ @@ -1029,6 +1049,7 @@ void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y, void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y, unsigned long delay) { + int regrab = 0; RAWFB_RET_VOID #if NO_X11 @@ -1039,11 +1060,16 @@ void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y, if (grab_ptr) { XUngrabPointer(dpy, CurrentTime); + regrab = 1; + } + if (grab_kbd && ungrab_both) { + XUngrabKeyboard(dpy, CurrentTime); + regrab = 1; } if (xtrap_input) { XTRAP_FakeMotionEvent_wr(dpy, screen, x, y, delay); - if (grab_ptr) { + if (regrab) { adjust_grabs(1, 1); } return; @@ -1056,7 +1082,7 @@ void XTestFakeMotionEvent_wr(Display* dpy, int screen, int x, int y, #if LIBVNCSERVER_HAVE_XTEST XTestFakeMotionEvent(dpy, screen, x, y, delay); #endif - if (grab_ptr) { + if (regrab) { adjust_grabs(1, 1); } #endif /* NO_X11 */