Commit ce2fdb72 authored by dscho's avatar dscho

new version of x11vnc from Karl Runge

parent 58551e93
/*
* x0vnc.c: a VNC server for X displays.
* x11vnc.c: a VNC server for X displays.
*
* Copyright (c) 2002 Karl J. Runge <runge@karlrunge.com> All rights reserved.
*
......@@ -21,45 +21,30 @@
*
* This program is based heavily on the following programs:
*
* original x11vnc.c of the libvncserver project (Johannes E. Schindelin)
* the originial x11vnc.c in libvncserver (Johannes E. Schindelin)
* krfb, the KDE desktopsharing project (Tim Jansen)
* x0rfbserver, the original native X vnc server (Jens Wagner)
*
* The primary goal of this program is to create a portable and simple
* command-line server utility that allows a VNC viewer to connect to an
* actual X display (as x11vnc, krfb, and x0rfbserver do). The only
* non-standard dependency of this program is the static library
* libvncserver.a (although in some environments libjpeg.so may not be
* readily available). To increase portability it is written in plain C.
* actual X display (as the above do). The only non-standard dependency
* of this program is the static library libvncserver.a (although in
* some environments libjpeg.so may not be readily available and needs
* to be installed, it may be found at ftp://ftp.uu.net/graphics/jpeg/).
* To increase portability it is written in plain C.
*
* The next goal is to improve performance and interactive response.
* The algorithm currently used here to achieve this is that of krfb
* (based on x0rfbserver algorithm). Additional heuristics are also
* applied. Currently there are a bit too many of these...
* applied (currently there are a bit too many of these...)
*
* To build:
* Obtain the libvncserver package (http://libvncserver.sourceforge.net)
* and ensure that "make" and "make x11vnc" work correctly. Defining
* HAVE_PTHREADS in the Makefile is recommended. One then could move the
* x11vnc.c file aside, copy this file in its place into the source tree,
* and issue:
*
* make x11vnc
* mv x11vnc x0vnc
*
* to create the x0vnc binary. Otherwise, with x0vnc.c copied to
* libvncserver source directory, something like this should work:
*
* gcc -Wall -DALLOW24BPP -I. -DBACKCHANNEL -c x0vnc.c
* gcc -o x0vnc x0vnc.o -L. -lvncserver -L/usr/local/lib -lz -ljpeg \
* -L/usr/X11R6/lib -lX11 -lXext -lXtst
*
* include -DHAVE_PTHREADS ... -lpthread to use threads.
*
* On Solaris the 2nd command might look something like:
*
* gcc -o x0vnc x0vnc.o -L. -lvncserver -L/usr/local/lib -lz -ljpeg \
* -lsocket -lnsl -L/usr/X/lib -R/usr/X/lib -lX11 -lXext -lXtst
* Obtain the libvncserver package (http://libvncserver.sourceforge.net).
* As of 12/2002 this version of x11vnc.c is contained in the libvncserver
* CVS tree. Parameters in the Makefile should be adjusted to the build
* system and then "make x11vnc" should create it. For earlier releases
* (say libvncserver-0.4) this file may be inserted in place of the
* original x11vnc.c file.
*/
#include <unistd.h>
......@@ -71,11 +56,24 @@
#include <X11/extensions/XTest.h>
#include <X11/keysym.h>
/*
* Work around Bool and KeySym same names in X and rfb.
* Bool is #define int in <X11/Xlib.h>
* KeySym is typedef XID in <X11/X.h>
* (note that X and rfb KeySym types are the same so a bit silly to worry...
* the Bool types are different though)
*/
typedef Bool X_Bool;
typedef KeySym X_KeySym;
/* the #define Bool can be removed: */
#ifdef Bool
#undef Bool
#endif
#define Bool RFBBool
/* the KeySym typedef cannot be removed, so use an alias for rest of file: */
#define KeySym RFBKeySym
#include "rfb.h"
Display *dpy = 0;
......@@ -129,6 +127,8 @@ int shared = 0; /* share vnc display. */
int view_only = 0; /* client can only watch. */
int connect_once = 1; /* allow only one client connection. */
int use_altgr = 0; /* use the altgr_keyboard modifier tweak */
/*
* waitms is the msec to wait between screen polls. Not too old h/w shows
* poll times of 15-35ms, so maybe this value cuts the rest load by 2 or so.
......@@ -143,7 +143,7 @@ int tile_fuzz = 2; /* tolerance for suspecting changed tiles touching */
/* a known changed tile. */
int grow_fill = 3; /* do the grow islands heuristic with this width. */
int gaps_fill = 4; /* do a final pass to try to fill gaps between tiles. */
double fs_frac = 0.5; /* threshold tile fraction to do fullscreen updates. */
double fs_frac = 0.6; /* threshold tile fraction to do fullscreen updates. */
#define NSCAN 32
int scanlines[NSCAN] = { /* scan pattern jitter from x0rfbserver */
......@@ -217,6 +217,115 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
return(RFB_CLIENT_ACCEPT);
}
/* For tweaking modifiers wrt the Alt-Graph key */
#define LEFTSHIFT 1
#define RIGHTSHIFT 2
#define ALTGR 4
char mod_state = 0;
char modifiers[0x100];
KeyCode keycodes[0x100], left_shift_code, right_shift_code, altgr_code;
void initialize_keycodes() {
X_KeySym key, *keymap;
int i, j, minkey, maxkey, syms_per_keycode;
memset(modifiers, -1, sizeof(modifiers));
XDisplayKeycodes(dpy, &minkey, &maxkey);
keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1),
&syms_per_keycode);
for (i = minkey; i <= maxkey; i++) {
for (j = 0; j < syms_per_keycode; j++) {
key = keymap[ (i - minkey) * syms_per_keycode + j ];
if ( key >= ' ' && key < 0x100
&& i == XKeysymToKeycode(dpy, key) ) {
keycodes[key] = i;
modifiers[key] = j;
}
}
}
left_shift_code = XKeysymToKeycode(dpy, XK_Shift_L);
right_shift_code = XKeysymToKeycode(dpy, XK_Shift_R);
altgr_code = XKeysymToKeycode(dpy, XK_Mode_switch);
XFree ((void *) keymap);
}
void tweak_mod(char mod, Bool down) {
Bool is_shift = mod_state & (LEFTSHIFT|RIGHTSHIFT);
X_Bool dn = (X_Bool) down;
if (mod < 0) {
return;
}
X_LOCK
if (is_shift && mod != 1) {
if (mod_state & LEFTSHIFT) {
XTestFakeKeyEvent(dpy, left_shift_code, !dn, CurrentTime);
}
if (mod_state & RIGHTSHIFT) {
XTestFakeKeyEvent(dpy, right_shift_code, !dn, CurrentTime);
}
}
if ( ! is_shift && mod == 1 ) {
XTestFakeKeyEvent(dpy, left_shift_code, dn, CurrentTime);
}
if ( (mod_state & ALTGR) && mod != 2 ) {
XTestFakeKeyEvent(dpy, altgr_code, !dn, CurrentTime);
}
if ( ! (mod_state & ALTGR) && mod == 2 ) {
XTestFakeKeyEvent(dpy, altgr_code, dn, CurrentTime);
}
X_UNLOCK
}
static void altgr_keyboard(Bool down, KeySym keysym, rfbClientPtr client) {
KeyCode k;
int tweak = 0;
if (view_only) {
return;
}
#define ADJUSTMOD(sym, state) \
if (keysym == sym) { \
if (down) { \
mod_state |= state; \
} else { \
mod_state &= ~state; \
} \
}
ADJUSTMOD(XK_Shift_L, LEFTSHIFT)
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT)
ADJUSTMOD(XK_Mode_switch, ALTGR)
if ( down && keysym >= ' ' && keysym < 0x100 ) {
tweak = 1;
tweak_mod(modifiers[keysym], True);
k = keycodes[keysym];
} else {
X_LOCK
k = XKeysymToKeycode(dpy, (X_KeySym) keysym);
X_UNLOCK
}
if ( k != NoSymbol ) {
X_LOCK
XTestFakeKeyEvent(dpy, k, (X_Bool) down, CurrentTime);
X_UNLOCK
}
if ( tweak ) {
tweak_mod(modifiers[keysym], False);
}
}
/* key event handler */
static void keyboard(Bool down, KeySym keysym, rfbClientPtr client) {
KeyCode k;
......@@ -225,18 +334,22 @@ static void keyboard(Bool down, KeySym keysym, rfbClientPtr client) {
return;
}
if (use_altgr) {
altgr_keyboard(down, keysym, client);
return;
}
X_LOCK
/* KeySym is XID in <X11/X.h> */
k = XKeysymToKeycode(dpy, (XID) keysym);
k = XKeysymToKeycode(dpy, (X_KeySym) keysym);
if ( k != NoSymbol ) {
/* Bool is int in <X11/Xlib.h> */
XTestFakeKeyEvent(dpy, k, (int) down, CurrentTime);
XTestFakeKeyEvent(dpy, k, (X_Bool) down, CurrentTime);
XFlush(dpy);
got_user_input++;
}
X_UNLOCK
}
......@@ -1212,7 +1325,7 @@ void watch_loop(void) {
void print_help() {
char help[] =
"x0vnc options:\n"
"x11vnc options:\n"
"\n"
"-defer time time in ms to wait for updates before sending to\n"
" client [rfbDeferUpdateTime] (default %d)\n"
......@@ -1231,6 +1344,9 @@ void print_help() {
" horizontal tiles into one big rectangle) (default %s).\n"
"-nohints do not use hints; send each tile separately.\n"
"\n"
"-altgr use a mechanism to properly handle the AltGr modifier\n"
" on certain keyboards (default %d).\n"
"-noaltgr send the keysym directly to the X server.\n"
"-threads use threaded algorithm [rfbRunEventLoop] if compiled\n"
" with threads (default %s).\n"
"-nothreads do not use [rfbRunEventLoop].\n"
......@@ -1242,8 +1358,9 @@ void print_help() {
;
fprintf(stderr, help, defer_update, waitms, gaps_fill, grow_fill,
fs_frac, tile_fuzz,
use_hints ? "on":"off", use_threads ? "on":"off",
view_only ? "on":"off", shared ? "on":"off");
use_hints ? "on":"off", use_altgr ? "on":"off",
use_threads ? "on":"off", view_only ? "on":"off",
shared ? "on":"off");
rfbUsage();
exit(1);
}
......@@ -1282,6 +1399,10 @@ int main(int argc, char** argv) {
use_threads = 1;
} else if (!strcmp(argv[i], "-nothreads")) {
use_threads = 0;
} else if (!strcmp(argv[i], "-altgr")) {
use_altgr = 1;
} else if (!strcmp(argv[i], "-noaltgr")) {
use_altgr = 0;
} else if (!strcmp(argv[i], "-viewonly")) {
view_only = 1;
} else if (!strcmp(argv[i], "-shared")) {
......@@ -1370,6 +1491,10 @@ int main(int argc, char** argv) {
initialize_shm();
if (use_altgr) {
initialize_keycodes();
}
printf("screen setup finished.\n");
watch_loop();
......
......@@ -139,7 +139,7 @@ void linecount (char* frame_buffer)
void on_key_press (Bool down,KeySym key,rfbClientPtr cl)
{
if (down) //or else the action occurs on both the press and depress
if (down) /* or else the action occurs on both the press and depress */
switch (key) {
case XK_b:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment