Commit 1c03dd4d authored by runge's avatar runge

x11vnc: -chatwindow, -scale WxH, -enc changes.

parent 16c7ea1b
......@@ -739,7 +739,7 @@ if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d dep=%d
if (attr->map_state == IsViewable &&
windows_8bpp[j].map_state != IsViewable) {
now_vis = 1;
}
}
if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", win, j, attr->map_state, attr->depth);
windows_8bpp[j].win = win;
windows_8bpp[j].top = top;
......
2008-10-19 Karl Runge <runge@karlrunge.com>
* x11vnc: -chatwindow for chat window on X console using SSVNC
as a helper. Print suggestion for X_ShmAttach failure.
Allow -scale WxH for different X- and Y-scaling factors.
Workaround for missing -enc cipher EVP_aes_256_cfb. Modify
message digest and salt/IV parameters. Try to improve compile
time by breaking up large if blocks.
2008-09-21 Karl Runge <runge@karlrunge.com>
* x11vnc: Add symmetric key encryption -enc cipher:keyfile,
works with SSVNC. Make -remap work on MacOSX console.
......
This diff is collapsed.
......@@ -226,6 +226,26 @@ int trap_getimage_xerror(Display *d, XErrorEvent *error) {
static int Xerror(Display *d, XErrorEvent *error) {
X_UNLOCK;
if (getenv("X11VNC_PRINT_XERROR")) {
fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n",
error->request_code, error->minor_code, error->error_code);
}
if (xshm_opcode > 0 && error->request_code == xshm_opcode) {
if (error->minor_code == X_ShmAttach) {
char *dstr = DisplayString(dpy);
fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n");
fprintf(stderr, " Is your DISPLAY=%s on a remote machine?\n", dstr);
if (strstr(dstr, "localhost:")) {
fprintf(stderr, " Note: DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n");
} else if (dstr[0] != ':') {
fprintf(stderr, " Note: DISPLAY=hostname:N suggests a remote display.\n");
}
fprintf(stderr, " Suggestion, use: x11vnc -display :0 ... for local display :0\n\n");
}
}
interrupted(0);
if (d) {} /* unused vars warning: */
......
......@@ -40,6 +40,7 @@ void set_client_input(char *str);
void set_child_info(void);
int cmd_ok(char *cmd);
void client_gone(rfbClientPtr client);
void client_gone_chat_helper(rfbClientPtr client);
void reverse_connect(char *str);
void set_vnc_connect_prop(char *str);
void read_vnc_connect_prop(int);
......@@ -48,6 +49,8 @@ void read_x11vnc_remote_prop(int);
void check_connect_inputs(void);
void check_gui_inputs(void);
enum rfbNewClientAction new_client(rfbClientPtr client);
enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client);
rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len);
void start_client_info_sock(char *host_port_cookie);
void send_client_info(char *str);
void adjust_grabs(int grab, int quiet);
......@@ -2469,7 +2472,7 @@ void reverse_connect(char *str) {
n = cnt;
if (n >= n_max) {
n = n_max;
}
}
t = sleep_max - sleep_min;
tot = sleep_min + ((n-1) * t) / (n_max-1);
......@@ -2788,6 +2791,40 @@ static void turn_off_truecolor_ad(rfbClientPtr client) {
}
}
/*
* some overrides for the local console text chat.
* could be useful in general for local helpers.
*/
rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len) {
if (cl != chat_window_client) {
rfbLog("invalid client during chat_helper login\n");
return FALSE;
} else {
if (!cl->host) {
rfbLog("empty cl->host during chat_helper login\n");
return FALSE;
}
if (strcmp(cl->host, "127.0.0.1")) {
rfbLog("invalid cl->host during chat_helper login: %s\n", cl->host);
return FALSE;
}
rfbLog("chat_helper login accepted\n");
return TRUE;
}
}
enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client) {
client->clientGoneHook = client_gone_chat_helper;
rfbLog("new chat helper\n");
return(RFB_CLIENT_ACCEPT);
}
void client_gone_chat_helper(rfbClientPtr client) {
rfbLog("finished chat helper\n");
chat_window_client = NULL;
}
/*
* libvncserver callback for when a new client connects
*/
......@@ -3119,11 +3156,11 @@ void send_client_info(char *str) {
buf += n;
len -= n;
continue;
}
}
if (n < 0 && errno == EINTR) {
continue;
}
}
close(sock);
icon_mode_socks[i] = -1;
break;
......
......@@ -19,6 +19,7 @@ extern void set_client_input(char *str);
extern void set_child_info(void);
extern int cmd_ok(char *cmd);
extern void client_gone(rfbClientPtr client);
extern void client_gone_chat_helper(rfbClientPtr client);
extern void reverse_connect(char *str);
extern void set_vnc_connect_prop(char *str);
extern void read_vnc_connect_prop(int);
......@@ -27,6 +28,8 @@ extern void read_x11vnc_remote_prop(int);
extern void check_connect_inputs(void);
extern void check_gui_inputs(void);
extern enum rfbNewClientAction new_client(rfbClientPtr client);
extern enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client);
extern rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len);
extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str);
extern void adjust_grabs(int grab, int quiet);
......
......@@ -555,6 +555,7 @@ static void setup_cursors(void) {
rfbCursorPtr rfb_curs;
char *scale = NULL;
int i, j, n = 0;
int w_in = 0, h_in = 0;
static int first = 1;
if (verbose) {
......@@ -689,17 +690,27 @@ static void setup_cursors(void) {
} else if (scaling && scale_str) {
scale = scale_str;
}
if (scale && sscanf(scale, "%dx%d", &i, &j) == 2) {
if (wdpy_x > 0) {
w_in = wdpy_x;
h_in = wdpy_y;
} else {
w_in = dpy_x;
h_in = dpy_y;
}
}
/* scale = NULL zeroes everything */
parse_scale_string(scale, &scale_cursor_fac, &scaling_cursor,
parse_scale_string(scale, &scale_cursor_fac_x, &scale_cursor_fac_y, &scaling_cursor,
&scaling_cursor_blend, &j, &j, &scaling_cursor_interpolate,
&scale_cursor_numer, &scale_cursor_denom);
&scale_cursor_numer, &scale_cursor_denom, w_in, h_in);
for (i=0; i<n; i++) {
/* create rfbCursors for the special cursors: */
cursor_info_t *ci = cursors[i];
if (scaling_cursor && scale_cursor_fac != 1.0) {
if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) {
int w, h, x, y, k;
unsigned long *pixels;
......@@ -982,7 +993,7 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
}
}
if (scaling_cursor && scale_cursor_fac != 1.0) {
if (scaling_cursor && (scale_cursor_fac_x != 1.0 || scale_cursor_fac_y != 1.0)) {
int W, H;
char *pixels_use = (char *) pixels;
unsigned int *pixels32 = NULL;
......@@ -990,8 +1001,8 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
W = w;
H = h;
w = scale_round(W, scale_cursor_fac);
h = scale_round(H, scale_cursor_fac);
w = scale_round(W, scale_cursor_fac_x);
h = scale_round(H, scale_cursor_fac_y);
pixels_new = (char *) malloc(4*w*h);
......@@ -1011,7 +1022,7 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
pixels_use = (char *) pixels32;
}
scale_rect(scale_cursor_fac, scaling_cursor_blend,
scale_rect(scale_cursor_fac_x, scale_cursor_fac_y, scaling_cursor_blend,
scaling_cursor_interpolate,
4, pixels_use, 4*W, pixels_new, 4*w,
W, H, w, h, 0, 0, W, H, 0);
......@@ -1040,8 +1051,8 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
pixels = (unsigned long *) pixels_new;
xhot = scale_round(xhot, scale_cursor_fac);
yhot = scale_round(yhot, scale_cursor_fac);
xhot = scale_round(xhot, scale_cursor_fac_x);
yhot = scale_round(yhot, scale_cursor_fac_y);
}
len = w * h;
......
This diff is collapsed.
This diff is collapsed.
......@@ -2700,7 +2700,7 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
X_LOCK;
XTestFakeKeyEvent_wr(dpy, k, (Bool) down, CurrentTime);
X_UNLOCK;
}
}
if ( tweak ) {
tweak_mod(modifiers[keysym], False);
......
......@@ -97,7 +97,7 @@ char *console_guess(char *str, int *fd) {
if (sscanf(in, "console%d", &n) != 1) {
tty = n;
have_uinput = 0;
}
}
}
if (! atparms) {
......
......@@ -388,6 +388,8 @@ int no_ultra_dpms = 0;
int no_ultra_ext = 0;
int saw_ultra_chat = 0;
int saw_ultra_file = 0;
int chat_window = 0;
rfbClientPtr chat_window_client = NULL;
int watch_selection = 1; /* normal selection/cutbuffer maintenance */
int watch_primary = 1; /* more dicey, poll for changes in PRIMARY */
......
......@@ -287,6 +287,8 @@ extern int no_ultra_dpms;
extern int no_ultra_ext;
extern int saw_ultra_chat;
extern int saw_ultra_file;
extern int chat_window;
extern rfbClientPtr chat_window_client;
extern int watch_selection;
extern int watch_primary;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -24,7 +24,7 @@ void free_tiles(void);
void shm_delete(XShmSegmentInfo *shm);
void shm_clean(XShmSegmentInfo *shm, XImage *xim);
void initialize_polling_images(void);
void scale_rect(double factor, int blend, int interpolate, int Bpp,
void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark);
void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark);
......@@ -428,7 +428,7 @@ void initialize_polling_images(void) {
if (! shm_create(&fullscreen_shm, &fullscreen, dpy_x,
dpy_y/fs_factor, "fullscreen")) {
clean_up_exit(1);
}
}
}
if (use_snapfb) {
if (! fs_factor) {
......@@ -437,7 +437,7 @@ void initialize_polling_images(void) {
} else if (! shm_create(&snaprect_shm, &snaprect, dpy_x,
dpy_y/fs_factor, "snaprect")) {
clean_up_exit(1);
}
}
}
/*
......@@ -737,7 +737,7 @@ weights for this scaled pixel are:
* the loop over the 4 pixels.
*/
void scale_rect(double factor, int blend, int interpolate, int Bpp,
void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark) {
/*
......@@ -773,7 +773,7 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
int b, k;
double pixave[4]; /* for averaging pixel values */
if (factor <= 1.0) {
if (factor_x <= 1.0 && factor_y <= 1.0) {
shrink = 1;
} else {
shrink = 0;
......@@ -787,8 +787,8 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
* This new way is probably the best we can do, take the inverse
* of the scaling factor to double precision.
*/
dx = 1.0/factor;
dy = 1.0/factor;
dx = 1.0/factor_x;
dy = 1.0/factor_y;
/*
* There is some speedup if the pixel weights are constant, so
......@@ -797,15 +797,18 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
* If scale = 1/n and n divides Nx and Ny, the pixel weights
* are constant (e.g. 1/2 => equal on 2x2 square).
*/
if (factor != last_factor || Nx != last_Nx || Ny != last_Ny) {
if (factor_x != last_factor || Nx != last_Nx || Ny != last_Ny) {
constant_weights = -1;
mag_int = -1;
last_Nx = Nx;
last_Ny = Ny;
last_factor = factor;
last_factor = factor_x;
}
if (constant_weights < 0 && factor_x != factor_y) {
constant_weights = 0;
mag_int = 0;
if (constant_weights < 0) {
} else if (constant_weights < 0) {
int n = 0;
constant_weights = 0;
......@@ -814,7 +817,7 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
for (i = 2; i<=128; i++) {
double test = ((double) 1)/ i;
double diff, eps = 1.0e-7;
diff = factor - test;
diff = factor_x - test;
if (-eps < diff && diff < eps) {
n = i;
break;
......@@ -839,18 +842,18 @@ void scale_rect(double factor, int blend, int interpolate, int Bpp,
for (i = 2; i<=32; i++) {
double test = (double) i;
double diff, eps = 1.0e-7;
diff = factor - test;
diff = factor_x - test;
if (-eps < diff && diff < eps) {
n = i;
break;
}
}
if (! blend && factor > 1.0 && n) {
if (! blend && factor_x > 1.0 && n) {
mag_int = n;
}
}
if (mark && factor > 1.0 && blend) {
if (mark && factor_x > 1.0 && blend) {
/*
* kludge: correct for interpolating blurring leaking
* up or left 1 destination pixel.
......@@ -1296,7 +1299,7 @@ void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark) {
dst_fb = rfb_fb;
dst_bpl = rfb_bytes_per_line;
scale_rect(scale_fac, scaling_blend, scaling_interpolate, fac * Bpp,
scale_rect(scale_fac_x, scale_fac_y, scaling_blend, scaling_interpolate, fac * Bpp,
src_fb, fac * main_bytes_per_line, dst_fb, dst_bpl, dpy_x, dpy_y,
scaled_x, scaled_y, X1, Y1, X2, Y2, mark);
}
......@@ -2623,7 +2626,7 @@ static void nap_set(int tile_cnt) {
if (! nap_ok && client_count) {
if(now > last_fb_bytes_sent + no_fbu_blank) {
if (debug_tiles > 1) {
printf("nap_set: nap_ok=1: now: %d last: %d\n",
fprintf(stderr, "nap_set: nap_ok=1: now: %d last: %d\n",
(int) now, (int) last_fb_bytes_sent);
}
nap_ok = 1;
......@@ -2683,10 +2686,16 @@ static void nap_check(int tile_cnt) {
dt_fbu = (int) (now - last_fb_bytes_sent);
if (dt_fbu > screen_blank) {
/* sleep longer for no fb requests */
if (debug_tiles > 1) {
fprintf(stderr, "screen blank sleep1: %d ms / 16\n", 2 * ms);
}
nap_sleep(2 * ms, 16);
return;
}
if (dt_ev > screen_blank) {
if (debug_tiles > 1) {
fprintf(stderr, "screen blank sleep2: %d ms / 8\n", ms);
}
nap_sleep(ms, 8);
return;
}
......@@ -2699,6 +2708,9 @@ static void nap_check(int tile_cnt) {
} else if (now - last_local_input <= 3) {
nap_ok = 0;
} else {
if (debug_tiles > 1) {
fprintf(stderr, "nap_check sleep: %d ms / 1\n", ms);
}
nap_sleep(ms, 1);
}
}
......
......@@ -11,7 +11,7 @@ extern void free_tiles(void);
extern void shm_delete(XShmSegmentInfo *shm);
extern void shm_clean(XShmSegmentInfo *shm, XImage *xim);
extern void initialize_polling_images(void);
extern void scale_rect(double factor, int blend, int interpolate, int Bpp,
extern void scale_rect(double factor_x, double factor_y, int blend, int interpolate, int Bpp,
char *src_fb, int src_bytes_per_line, char *dst_fb, int dst_bytes_per_line,
int Nx, int Ny, int nx, int ny, int X1, int Y1, int X2, int Y2, int mark);
extern void scale_and_mark_rect(int X1, int Y1, int X2, int Y2, int mark);
......
This diff is collapsed.
......@@ -15,8 +15,8 @@ extern void check_padded_fb(void);
extern void install_padded_fb(char *geom);
extern XImage *initialize_xdisplay_fb(void);
extern XImage *initialize_raw_fb(int);
extern void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom);
extern void parse_scale_string(char *str, double *factor_x, double *factor_y, int *scaling, int *blend,
int *nomult4, int *pad, int *interpolate, int *numer, int *denom, int w_in, int h_in);
extern int parse_rotate_string(char *str, int *mode);
extern int scale_round(int len, double fac);
extern void initialize_screen(int *argc, char **argv, XImage *fb);
......
......@@ -165,7 +165,7 @@ void selection_request(XEvent *ev, char *type) {
if (debug_sel) {
rfbLog("XSendEvent() -> %d\n", ret);
}
}
}
if (trapped_xerror) {
rfbLog("selection_request: ignored XError while sending "
"%s selection to 0x%x.\n", type, req_event->requestor);
......
......@@ -706,7 +706,7 @@ static char *dcop_session(void) {
} else {
if (sess2) {
free(sess2);
}
}
sess2 = strdup(q);
}
}
......
......@@ -128,6 +128,11 @@ Clients
tightfilexfer
ultrafilexfer
proxy:
=GAL Chat::
chatwindow
=DRA chaton
=DRA chatoff
=GAL LOFF
=GAL Java-applet::
=D http
httpdir:
......@@ -1061,6 +1066,12 @@ The default port listened on is 5800, so the URL is typically:
http://hostname:5800/
but this can be altered by -httpport, etc.
"
set helptext(Chat:) "
In this sub-menu are some options for enabling a local chat window
and starting or stopping the current chat. This is the UltraVNC
Text Chat support in x11vnc.
"
set helptext(ScrollCopyRect:) "
......
......@@ -139,6 +139,11 @@ char gui_code[] = "";
" tightfilexfer\n"
" ultrafilexfer\n"
" proxy:\n"
" =GAL Chat::\n"
" chatwindow\n"
" =DRA chaton\n"
" =DRA chatoff\n"
" =GAL LOFF\n"
" =GAL Java-applet::\n"
" =D http\n"
" httpdir:\n"
......@@ -1074,6 +1079,12 @@ char gui_code[] = "";
"but this can be altered by -httpport, etc.\n"
"\"\n"
"\n"
" set helptext(Chat:) \"\n"
"In this sub-menu are some options for enabling a local chat window\n"
"and starting or stopping the current chat. This is the UltraVNC \n"
"Text Chat support in x11vnc.\n"
"\"\n"
"\n"
" set helptext(ScrollCopyRect:) \"\n"
"This sub-menu has some options for the x11vnc Scroll detection and\n"
"CopyRect speedup scheme.\n"
......
......@@ -155,8 +155,8 @@ void unixpw_screen(int init) {
y = dpy_y / 4;
if (scaling) {
x = (int) (x * scale_fac);
y = (int) (y * scale_fac);
x = (int) (x * scale_fac_x);
y = (int) (y * scale_fac_y);
x = nfix(x, scaled_x);
y = nfix(y, scaled_y);
}
......@@ -1231,10 +1231,10 @@ void unixpw_keystroke(rfbBool down, rfbKeySym keysym, int init) {
x = text_x();
y = text_y();
if (scaling) {
int x2 = x / scale_fac;
int y2 = y / scale_fac;
int w2 = char_w / scale_fac;
int h2 = char_h / scale_fac;
int x2 = x / scale_fac_x;
int y2 = y / scale_fac_y;
int w2 = char_w / scale_fac_x;
int h2 = char_h / scale_fac_y;
x2 = nfix(x2, dpy_x);
y2 = nfix(y2, dpy_y);
......
......@@ -1189,6 +1189,7 @@ void user_supplied_opts(char *opts) {
"geometry", "geom", "ge",
"noncache", "nc",
"nodisplay", "nd",
"viewonly", "vo",
NULL
};
......@@ -1247,6 +1248,8 @@ void user_supplied_opts(char *opts) {
if (!solid_str) {
solid_str = strdup(solid_default);
}
} else if (!strcmp(p, "viewonly") || !strcmp(p, "vo")) {
view_only = 1;
} else if (strstr(p, "solid=") == p ||
strstr(p, "so=") == p) {
use_solid_bg = 1;
......@@ -1826,6 +1829,7 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
char fdgeom[128], fdsess[128], fdopts[128], fdprog[128];
char fdxsrv[128], fdxdum[128], fdcups[128], fdesd[128];
char fdnas[128], fdsmb[128], fdtag[128];
char cdout[128];
if (opts) {
opts++;
......@@ -1847,6 +1851,7 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
fdnas[0] = '\0';
fdsmb[0] = '\0';
fdtag[0] = '\0';
cdout[0] = '\0';
if (unixpw && keep_unixpw_opts && keep_unixpw_opts[0] != '\0') {
char *q, *p, *t = strdup(keep_unixpw_opts);
......@@ -1955,6 +1960,9 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
if (fdxdum[0] == '\0' && getenv("FD_XDUMMY_NOROOT")) {
snprintf(fdxdum, 120, "%s", getenv("FD_XDUMMY_NOROOT"));
}
if (getenv("CREATE_DISPLAY_OUTPUT")) {
snprintf(cdout, 120, "CREATE_DISPLAY_OUTPUT='%s'", getenv("CREATE_DISPLAY_OUTPUT"));
}
set_env("FD_GEOM", fdgeom);
set_env("FD_OPTS", fdopts);
......@@ -1998,13 +2006,14 @@ static char *build_create_cmd(char *cmd, int *saw_xdmcp, char *usslpeer, char *t
+ strlen(fdtag) + 1
+ strlen(fdxdum) + 1
+ strlen(fdsess) + 1
+ strlen(cdout) + 1
+ strlen(opts) + 1);
sprintf(create_cmd, "env USER='%s' FD_GEOM='%s' FD_SESS='%s' "
"FD_OPTS='%s' FD_PROG='%s' FD_XSRV='%s' FD_CUPS='%s' "
"FD_ESD='%s' FD_NAS='%s' FD_SMB='%s' FD_TAG='%s' "
"FD_XDUMMY_NOROOT='%s' /bin/sh %s %s",
"FD_XDUMMY_NOROOT='%s' %s /bin/sh %s %s",
uu, fdgeom, fdsess, fdopts, fdprog, fdxsrv,
fdcups, fdesd, fdnas, fdsmb, fdtag, fdxdum, tmp, opts);
fdcups, fdesd, fdnas, fdsmb, fdtag, fdxdum, cdout, tmp, opts);
} else {
create_cmd = (char *) malloc(strlen(tmp)
+ strlen("/bin/sh ") + 1 + strlen(opts) + 1);
......@@ -2158,6 +2167,7 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
if (!strcmp(cmd, "FINDDISPLAY") ||
strstr(cmd, "FINDCREATEDISPLAY") == cmd) {
char *nd = "";
char fdout[128];
tmp_fd = mkstemp(tmp);
if (tmp_fd < 0) {
rfbLog("wait_for_client: open failed: %s\n", tmp);
......@@ -2183,9 +2193,14 @@ static int do_run_cmd(char *cmd, char *create_cmd, char *users_list_save, int cr
}
check_nodisplay(&nd);
fdout[0] = '\0';
if (getenv("FIND_DISPLAY_OUTPUT")) {
snprintf(fdout, 120, " FIND_DISPLAY_OUTPUT='%s' ", getenv("FIND_DISPLAY_OUTPUT"));
}
cmd = (char *) malloc(strlen("env X11VNC_SKIP_DISPLAY='' ")
+ strlen(nd) + strlen(tmp) + strlen("/bin/sh ") + 1);
sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' /bin/sh %s", nd, tmp);
+ strlen(nd) + strlen(tmp) + strlen("/bin/sh ") + strlen(fdout) + 1);
sprintf(cmd, "env X11VNC_SKIP_DISPLAY='%s' %s /bin/sh %s", nd, fdout, tmp);
}
rfbLog("wait_for_client: running: %s\n", cmd);
......
......@@ -2492,7 +2492,7 @@ static int check_xrecord_keys(void) {
get_out = 1;
if (got_keyboard_input) {
get_out = 0;
}
}
dtime0(&tnow);
if (tnow < last_key_scroll + scroll_persist) {
......@@ -2735,10 +2735,10 @@ static int check_xrecord_mouse(void) {
get_out = 1;
if (button_mask) {
get_out = 0;
}
}
if (want_back_in) {
get_out = 0;
}
}
dtime0(&tnow);
if (0) fprintf(stderr, "check_xrecord_mouse: IN xrecording: %d\n", xrecording);
......@@ -8116,7 +8116,7 @@ void scale_mark_xrootpmap(void) {
dst_fb = rfb_fb;
dst_bpl = rfb_bytes_per_line;
scale_rect(scale_fac, scaling_blend, scaling_interpolate, fac * Bpp,
scale_rect(scale_fac_x, scale_fac_y, scaling_blend, scaling_interpolate, fac * Bpp,
src_fb, fac * main_bytes_per_line, dst_fb, dst_bpl, dpy_x, yfac * dpy_y,
scaled_x, yfac * scaled_y, 0, yn, dpy_x, yn + dpy_y, mark);
}
......@@ -8303,7 +8303,7 @@ void read_events(int *n_in) {
if (w_new != wd || h_new != ht) {
msg = "change size";
cfg_size = 1;
}
}
if (x_new != x || y_new != y) {
if (!strcmp(msg, "")) {
msg = "change position";
......@@ -9939,14 +9939,14 @@ if (ncdb) fprintf(stderr, "----%02d: MapNotify 0x%lx %3d\n", ik, win, id
save = 0;
}
sraRgnDestroy(r);
}
}
if (missed_bs_restore) {
r = idx_create_rgn(r0, idx);
if (sraRgnAnd(r, missed_bs_restore_rgn)) {
save = 0;
}
sraRgnDestroy(r);
}
}
if (save) {
valid = 0;
su_save(idx, nbatch, &attr, 1, &valid, 1);
......@@ -10040,14 +10040,14 @@ if (ncdb) fprintf(stderr, "----%02d: UnmapNotify 0x%lx %3d\n", ik, win, id
save = 0;
}
sraRgnDestroy(r);
}
}
if (missed_bs_restore) {
r = idx_create_rgn(r0, idx);
if (sraRgnAnd(r, missed_bs_restore_rgn)) {
save = 0;
}
sraRgnDestroy(r);
}
}
if (save) {
valid = 0;
bs_save(idx, nbatch, &attr, 1, 0, &valid, 1);
......
.\" This file was automatically generated from x11vnc -help output.
.TH X11VNC "1" "September 2008" "x11vnc " "User Commands"
.TH X11VNC "1" "October 2008" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.9.5, lastmod: 2008-09-21
version: 0.9.5, lastmod: 2008-10-18
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -336,6 +336,10 @@ is taken as a floating point number, alternatively
the notation "m/n" may be used to denote fractions
exactly, e.g. \fB-scale\fR 2/3
.IP
To scale asymmetrically in the horizontal and vertical
directions, specify a WxH geometry to stretch to:
e.g. '-scale 1024x768', or also '-scale 0.9x0.75'
.IP
Scaling Options: can be added after \fIfraction\fR via
":", to supply multiple ":" options use commas.
If you just want a quick, rough scaling without
......@@ -356,6 +360,10 @@ scheme even when shrinking, ":pad" pad scaled width
and height to be multiples of scaling denominator
(e.g. 3 for 2/3).
.PP
\fB-geometry\fR \fIWxH\fR
.IP
Same as \fB-scale\fR WxH
.PP
\fB-scale_cursor\fR \fIfrac\fR
.IP
By default if \fB-scale\fR is supplied the cursor shape is
......@@ -1953,9 +1961,9 @@ to tunnelling with the symmetric cipher (an unfortunate
choice of implementation).
.IP
cipher can be one of: arc4, aesv2, aes-cfb, blowfish,
or 3des. See the OpenSSL documentation for more info.
The keysize is 128 bits. Here is one way to make a
keyfile with that many bits:
aes256, or 3des. See the OpenSSL documentation for
more info. The keysize is 128 bits (except for aes256).
Here is one way to make a keyfile with that many bits:
.IP
dd if=/dev/random of=./my.key bs=16 count=1
.IP
......@@ -1994,6 +2002,18 @@ It is not a good idea to set either one to zero,
although you may be forced to if the other side of the
tunnel is not under your control.
.IP
To skip the salt and EVP_BytesToKey MD5 entirely (no
hashing is done: the keydata is directly inserted into
the cipher) specify "-1" for the salt, e.g.
.IP
\fB-enc\fR blowfish@-1,16:./my.key
.IP
The message digest can also be changed to something
besides the default MD5. Use cipher@md+n,m where "md"
can be one of sha, sha1, md5, or ripe. For example:
.IP
\fB-enc\fR arc4@sha+8,16:./my.key
.IP
The SSVNC vnc viewer project supplies a symmetric
encryption tool named "ultravnc_dsm_helper" that can
be used on the viewer side. For example:
......@@ -2003,16 +2023,22 @@ ssvncviewer exec='ultravnc_dsm_helper arc4 my.key 0 h:p'
where h:p is the hostname and port of the x11vnc server.
ultravnc_dsm_helper may also be used standalone to
provide a symmetric encryption tunnel for any viewer
or server (VNC or otherwise.)
or server (VNC or otherwise.) The cipher (1st arg)
is basically the same syntax as we use above.
.IP
Also see the 'Non-Ultra DSM' SSVNC option for the
\'UltraVNC DSM Encryption Plugin' advanced option.
.IP
For both ways of using the viewer, you can specify the
salt,ivec sizes (in GUI or, e.g. arc4@8,16).
.PP
\fB-https\fR \fI[port]\fR
.IP
Choose a separate HTTPS port (-ssl mode only).
Use a special, separate HTTPS port (-ssl mode only)
for HTTPS Java viewer applet downloading. I.e. not 5900
and not 5800 (the defaults.)
.IP
In \fB-ssl\fR mode, it turns out you can use the
BACKGROUND: In \fB-ssl\fR mode, it turns out you can use the
single VNC port (e.g. 5900) for both VNC and HTTPS
connections. (HTTPS is used to retrieve a SSL-aware
VncViewer.jar applet that is provided with x11vnc).
......@@ -2030,14 +2056,15 @@ ponder the Certificate dialogs in his browser, Java VM,
or VNC Viewer applet. That's right 3 separate "Are
you sure you want to connect?" dialogs!)
.IP
So use the \fB-https\fR option to provide a separate, more
reliable HTTPS port that x11vnc will listen on. If
USAGE: So use the \fB-https\fR option to provide a separate,
more reliable HTTPS port that x11vnc will listen on. If
[port] is not provided (or is 0), one is autoselected.
The URL to use is printed out at startup.
.IP
The SSL Java applet directory is specified via the
\fB-httpdir\fR option. If not supplied it will try to guess
the directory as though the \fB-http\fR option was supplied.
\fB-httpdir\fR option. If not supplied, \fB-https\fR will try
to guess the directory as though the \fB-http\fR option
was supplied.
.PP
\fB-httpsredir\fR \fI[port]\fR
.IP
......@@ -3805,6 +3832,27 @@ Disable the following UltraVNC extensions: SingleWindow
and ServerInput. The others managed by libvncserver
(textchat, 1/n scaling, rfbEncodingUltra) are not.
.PP
\fB-chatwindow\fR
.IP
Place a local UltraVNC chat window on the X11 display
that x11vnc is polling. That way the person on the VNC
viewer-side can chat with the person at the physical
X11 console. (e.g. helpdesk w/o telephone)
.IP
For this to work the SSVNC package (version 1.0.21 or
later) MUST BE installed on the system where x11vnc runs
and the 'ssvnc' command must be available in $PATH.
The ssvncviewer is used as a chat window helper.
See http://www.karlrunge.com/x11vnc/ssvnc.html
.IP
This option implies '-rfbversion 3.6' so as to trick
UltraVNC viewers, otherwise they assume chat is not
available. To specify a different rfbversion, place
it after the \fB-chatwindow\fR option on the cmdline.
.IP
See also the remote control 'chaton' and 'chatoff'
actions. These can also be set from the tkx11vnc GUI.
.PP
\fB-noxdamage\fR
.IP
Do not use the X DAMAGE extension to detect framebuffer
......@@ -5004,6 +5052,14 @@ noultraext enable \fB-noultraext\fR mode.
.IP
ultraext disable \fB-noultraext\fR mode.
.IP
chatwindow enable local chatwindow mode.
.IP
nochatwindow disable local chatwindow mode.
.IP
chaton begin chat using local window.
.IP
chatoff end chat using local window.
.IP
xdamage enable xdamage polling hints.
.IP
noxdamage disable xdamage polling hints.
......@@ -5213,16 +5269,17 @@ nowireframe nowf wireframelocal wfl nowireframelocal
nowfl wirecopyrect wcr nowirecopyrect nowcr scr_area
scr_skip scr_inc scr_keys scr_term scr_keyrepeat
scr_parms scrollcopyrect scr noscrollcopyrect noscr
fixscreen noxrecord xrecord reset_record pointer_mode pm
input_skip allinput noallinput input grabkbd nograbkbd
grabptr nograbptr grabalways nograbalways grablocal
client_input ssltimeout speeds wmdt debug_pointer dp
nodebug_pointer nodp debug_keyboard dk nodebug_keyboard
nodk keycode deferupdate defer wait_ui wait_bog
nowait_bog slow_fb xrefresh wait readtimeout nap nonap
sb screen_blank fbpm nofbpm dpms nodpms clientdpms
noclientdpms forcedpms noforcedpms noserverdpms
serverdpms noultraext ultraext fs gaps grow fuzz snapfb
fixscreen noxrecord xrecord reset_record pointer_mode
pm input_skip allinput noallinput input grabkbd
nograbkbd grabptr nograbptr grabalways nograbalways
grablocal client_input ssltimeout speeds wmdt
debug_pointer dp nodebug_pointer nodp debug_keyboard
dk nodebug_keyboard nodk keycode deferupdate defer
wait_ui wait_bog nowait_bog slow_fb xrefresh wait
readtimeout nap nonap sb screen_blank fbpm nofbpm dpms
nodpms clientdpms noclientdpms forcedpms noforcedpms
noserverdpms serverdpms noultraext ultraext chatwindow
nochatwindow chaton chatoff fs gaps grow fuzz snapfb
nosnapfb rawfb uinput_accel uinput_thresh uinput_reset
uinput_always progressive rfbport http nohttp httpport
httpdir enablehttpproxy noenablehttpproxy alwaysshared
......@@ -5239,9 +5296,9 @@ macnoresize macresize nomacnoresize maciconanim macmenu
macnomenu nomacmenu macuskbd nomacuskbd noremote
.IP
aro= noop display vncdisplay desktopname guess_desktop
http_url auth xauth users rootshift clipshift
scale_str scaled_x scaled_y scale_numer scale_denom
scale_fac scaling_blend scaling_nomult4 scaling_pad
http_url auth xauth users rootshift clipshift scale_str
scaled_x scaled_y scale_numer scale_denom scale_fac_x
scale_fac_y scaling_blend scaling_nomult4 scaling_pad
scaling_interpolate inetd privremote unsafe safer
nocmds passwdfile unixpw unixpw_nis unixpw_list ssl
ssl_pem sslverify stunnel stunnel_pem https httpsredir
......
This diff is collapsed.
......@@ -423,7 +423,8 @@ extern int raw_fb_bytes_per_line; /* of actual raw region we poll, not our raw_f
/* scaling parameters */
extern char *scale_str;
extern double scale_fac;
extern double scale_fac_x;
extern double scale_fac_y;
extern int scaling;
extern int scaling_blend; /* for no blending option (very course) */
extern int scaling_nomult4; /* do not require width = n * 4 */
......@@ -438,7 +439,8 @@ extern int rotating_cursors;
/* scale cursor */
extern char *scale_cursor_str;
extern double scale_cursor_fac;
extern double scale_cursor_fac_x;
extern double scale_cursor_fac_y;
extern int scaling_cursor;
extern int scaling_cursor_blend;
extern int scaling_cursor_interpolate;
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.9.5 lastmod: 2008-09-21";
char lastmod[] = "0.9.5 lastmod: 2008-10-18";
/* X display info */
......@@ -86,7 +86,8 @@ int raw_fb_bytes_per_line = 0;
/* scaling parameters */
char *scale_str = NULL;
double scale_fac = 1.0;
double scale_fac_x = 1.0;
double scale_fac_y = 1.0;
int scaling = 0;
int scaling_blend = 1; /* for no blending option (very course) */
int scaling_nomult4 = 0; /* do not require width = n * 4 */
......@@ -101,7 +102,8 @@ int rotating_cursors = 0;
/* scale cursor */
char *scale_cursor_str = NULL;
double scale_cursor_fac = 1.0;
double scale_cursor_fac_x = 1.0;
double scale_cursor_fac_y = 1.0;
int scaling_cursor = 0;
int scaling_cursor_blend = 1;
int scaling_cursor_interpolate = 0;
......
......@@ -1494,27 +1494,137 @@ void set_server_input(rfbClientPtr cl, int grab) {
#endif
}
static int wsock_timeout_sock = -1;
static void wsock_timeout (int sig) {
rfbLog("sig: %d, wsock_timeout.\n", sig);
if (wsock_timeout_sock >= 0) {
close(wsock_timeout_sock);
wsock_timeout_sock = -1;
}
}
static void try_local_chat_window(void) {
int i, port, lsock;
char cmd[100];
struct sockaddr_in addr;
#ifdef __hpux
int addrlen = sizeof(addr);
#else
socklen_t addrlen = sizeof(addr);
#endif
for (i = 0; i < 90; i++) {
/* find an open port */
port = 7300 + i;
lsock = rfbListenOnTCPPort(port, htonl(INADDR_LOOPBACK));
if (lsock >= 0) {
break;
}
port = 0;
}
if (port == 0) {
return;
}
/* have ssvncvncviewer connect back to us (n.b. sockpair fails) */
sprintf(cmd, "ssvnc -cmd VNC://localhost:%d -chatonly", port);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
return;
} else if (pid == 0) {
char *args[4];
int d;
args[0] = "/bin/sh";
args[1] = "-c";
/* "ssvnc -cmd VNC://fd=0 -chatonly"; */
args[2] = cmd;
args[3] = NULL;
for (d = 3; d < 256; d++) {
close(d);
}
set_env("VNCVIEWER_PASSWORD", "moo");
execvp(args[0], args);
perror("exec");
exit(1);
} else {
int i, sock = -1;
rfbNewClientHookPtr new_save;
signal(SIGALRM, wsock_timeout);
wsock_timeout_sock = lsock;
alarm(10);
sock = accept(lsock, (struct sockaddr *)&addr, &addrlen);
alarm(0);
signal(SIGALRM, SIG_DFL);
close(lsock);
if (sock < 0) {
return;
}
new_save = screen->newClientHook;
screen->newClientHook = new_client_chat_helper;
chat_window_client = rfbNewClient(screen, sock);
screen->newClientHook = new_save;
if (chat_window_client != NULL) {
rfbPasswordCheckProcPtr pwchk_save = screen->passwordCheck;
rfbBool save_shared1 = screen->alwaysShared;
rfbBool save_shared2 = screen->neverShared;
screen->alwaysShared = TRUE;
screen->neverShared = FALSE;
screen->passwordCheck = password_check_chat_helper;
for (i=0; i<30; i++) {
rfbPE(-1);
if (!chat_window_client) {
break;
}
if (chat_window_client->state == RFB_NORMAL) {
break;
}
}
screen->passwordCheck = pwchk_save;
screen->alwaysShared = save_shared1;
screen->neverShared = save_shared2;
}
}
}
void set_text_chat(rfbClientPtr cl, int len, char *txt) {
int dochat = 1;
rfbClientIteratorPtr iter;
rfbClientPtr cl2;
unsigned int ulen = (unsigned int) len;
if (no_ultra_ext || ! dochat) {
return;
}
#if 0
rfbLog("set_text_chat: len=%d\n", len);
rfbLog("set_text_chat: len=0x%x txt='", len);
if (0 < len && len < 10000) write(2, txt, len);
fprintf(stderr, "'\n");
#endif
if (unixpw_in_progress) {
rfbLog("set_text_chat: unixpw_in_progress, dropping client.\n");
rfbCloseClient(cl);
return;
}
if (chat_window && chat_window_client == NULL && ulen == rfbTextChatOpen) {
try_local_chat_window();
}
saw_ultra_chat = 1;
iter = rfbGetClientIterator(screen);
......@@ -1523,10 +1633,15 @@ void set_text_chat(rfbClientPtr cl, int len, char *txt) {
if (cl2 == cl) {
continue;
}
if (cl2->state != RFB_NORMAL) {
continue;
}
if (ulen == rfbTextChatOpen) {
rfbSendTextChatMessage(cl2, rfbTextChatOpen, "");
} else if (ulen == rfbTextChatClose) {
rfbSendTextChatMessage(cl2, rfbTextChatClose, "");
/* not clear what is going on WRT close and finished... */
rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
} else if (ulen == rfbTextChatFinished) {
rfbSendTextChatMessage(cl2, rfbTextChatFinished, "");
} else if (len <= rfbTextMaxSize) {
......@@ -1534,6 +1649,11 @@ void set_text_chat(rfbClientPtr cl, int len, char *txt) {
}
}
rfbReleaseClientIterator(iter);
if (ulen == rfbTextChatClose && cl != NULL) {
/* not clear what is going on WRT close and finished... */
rfbSendTextChatMessage(cl, rfbTextChatFinished, "");
}
}
int get_keyboard_led_state_hook(rfbScreenInfoPtr s) {
......
......@@ -328,7 +328,7 @@ static void initialize_xinerama (void) {
xinerama = 0;
xinerama_present = 0;
return;
}
}
xinerama_present = 1;
rfbLog("\n");
rfbLog("Xinerama is present and active (e.g. multi-head).\n");
......
......@@ -162,6 +162,8 @@ int check_xrandr_event(char *msg) {
if (! xrandr && ! xrandr_maybe) {
return 0;
}
if (xrandr_base_event_type && XCheckTypedEvent(dpy,
xrandr_base_event_type + RRScreenChangeNotify, &xev)) {
int do_change, qout = 0;
......@@ -172,7 +174,9 @@ int check_xrandr_event(char *msg) {
if (first && ! xrandr) {
fprintf(stderr, "\n");
qout = 1;
if (getenv("X11VNC_DEBUG_XRANDR") == NULL) {
qout = 1;
}
}
first = 0;
......@@ -230,11 +234,15 @@ int check_xrandr_event(char *msg) {
XDisplayWidth(dpy, scr), XDisplayHeight(dpy, scr));
rfbLog("check_xrandr_event(): returning control to"
" caller...\n");
return do_change;
}
#else
xev.type = 0;
#endif
return 0;
}
......
......@@ -52,6 +52,7 @@ extern int known_xrandr_mode(char *s);
} \
trapped_getimage_xerror = 0; \
XSetErrorHandler(old_getimage_handler); \
XFlush_wr(dpy); \
check_xrandr_event(y); \
X_UNLOCK; \
return(x); \
......
......@@ -372,7 +372,7 @@ int xrecord_skip_keysym(rfbKeySym keysym) {
int xrecord_skip_button(int new, int old) {
/* unused vars warning: */
if (new || old) {}
if (new || old) {}
return 0;
}
......@@ -1309,7 +1309,7 @@ static void record_grab(XPointer ptr, XRecordInterceptData *rec_data) {
XRecordFreeData(rec_data);
/* unused vars warning: */
if (ptr) {}
if (ptr) {}
}
#endif
......
......@@ -9,6 +9,7 @@
#include "macosx.h"
int xshm_present = 0;
int xshm_opcode = 0;
int xtest_present = 0;
int xtrap_present = 0;
int xrecord_present = 0;
......@@ -32,6 +33,7 @@ XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth,
Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
Bool XShmQueryExtension_wr(Display *disp);
int XShmGetEventBase_wr(Display *disp);
XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
unsigned int width, unsigned int height, Bool show_cursor);
......@@ -203,6 +205,15 @@ Bool XShmQueryExtension_wr(Display *disp) {
#endif
}
int XShmGetEventBase_wr(Display *disp) {
#if LIBVNCSERVER_HAVE_XSHM
return XShmGetEventBase(disp);
#else
if (!disp) {}
return 0;
#endif
}
/* wrapper for overlay screen reading: */
XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
......@@ -224,7 +235,7 @@ XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
}
# else
/* unused vars warning: */
if (disp || d || x || y || width || height || show_cursor) {}
if (disp || d || x || y || width || height || show_cursor) {}
return NULL;
# endif
......@@ -631,7 +642,7 @@ void XTRAP_FakeKeyEvent_wr(Display* dpy, KeyCode key, Bool down,
return;
}
/* unused vars warning: */
if (key || down || delay) {}
if (key || down || delay) {}
# if LIBVNCSERVER_HAVE_LIBXTRAP
XESimulateXEventRequest(trap_ctx, down ? KeyPress : KeyRelease,
......@@ -722,7 +733,7 @@ void XTRAP_FakeButtonEvent_wr(Display* dpy, unsigned int button, Bool is_press,
return;
}
/* unused vars warning: */
if (button || is_press || delay) {}
if (button || is_press || delay) {}
#if LIBVNCSERVER_HAVE_LIBXTRAP
XESimulateXEventRequest(trap_ctx,
......@@ -788,7 +799,7 @@ void XTRAP_FakeMotionEvent_wr(Display* dpy, int screen, int x, int y,
return;
}
/* unused vars warning: */
if (dpy || screen || x || y || delay) {}
if (dpy || screen || x || y || delay) {}
#if LIBVNCSERVER_HAVE_LIBXTRAP
XESimulateXEventRequest(trap_ctx, MotionNotify, 0, x, y, 0);
......@@ -891,7 +902,7 @@ Bool XETrapQueryExtension_wr(Display *dpy, int *ev, int *er, int *op) {
(INT32 *)op);
#else
/* unused vars warning: */
if (ev || er || op) {}
if (ev || er || op) {}
return False;
#endif
}
......@@ -913,7 +924,7 @@ int XTestGrabControl_wr(Display *dpy, Bool impervious) {
int XTRAP_GrabControl_wr(Display *dpy, Bool impervious) {
if (! xtrap_present) {
/* unused vars warning: */
if (dpy || impervious) {}
if (dpy || impervious) {}
return 0;
}
RAWFB_RET(0)
......
......@@ -4,6 +4,7 @@
/* -- xwrappers.h -- */
extern int xshm_present;
extern int xshm_opcode;
extern int xtest_present;
extern int xtrap_present;
extern int xrecord_present;
......@@ -27,6 +28,7 @@ extern XImage *XShmCreateImage_wr(Display* disp, Visual* vis, unsigned int depth
extern Status XShmAttach_wr(Display *disp, XShmSegmentInfo *shminfo);
extern Status XShmDetach_wr(Display *disp, XShmSegmentInfo *shminfo);
extern Bool XShmQueryExtension_wr(Display *disp);
extern int XShmGetEventBase_wr(Display *disp);
extern XImage *xreadscreen(Display *disp, Drawable d, int x, int y,
unsigned int width, unsigned int height, Bool show_cursor);
......
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