diff options
Diffstat (limited to 'x11vnc/screen.c')
-rw-r--r-- | x11vnc/screen.c | 4705 |
1 files changed, 0 insertions, 4705 deletions
diff --git a/x11vnc/screen.c b/x11vnc/screen.c deleted file mode 100644 index d0851f6..0000000 --- a/x11vnc/screen.c +++ /dev/null @@ -1,4705 +0,0 @@ -/* - Copyright (C) 2002-2010 Karl J. Runge <[email protected]> - All rights reserved. - -This file is part of x11vnc. - -x11vnc 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. - -x11vnc 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 x11vnc; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -or see <http://www.gnu.org/licenses/>. - -In addition, as a special exception, Karl J. Runge -gives permission to link the code of its release of x11vnc with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. -*/ - -/* -- screen.c -- */ - -#include "x11vnc.h" -#include "xevents.h" -#include "xwrappers.h" -#include "xinerama.h" -#include "xdamage.h" -#include "win_utils.h" -#include "cleanup.h" -#include "userinput.h" -#include "scan.h" -#include "user.h" -#include "rates.h" -#include "pointer.h" -#include "keyboard.h" -#include "cursor.h" -#include "connections.h" -#include "remote.h" -#include "unixpw.h" -#include "sslcmds.h" -#include "sslhelper.h" -#include "v4l.h" -#include "linuxfb.h" -#include "macosx.h" -#include "macosxCG.h" -#include "avahi.h" -#include "solid.h" -#include "inet.h" -#include "xrandr.h" -#include "xrecord.h" -#include "pm.h" - -#include <rfb/rfbclient.h> - -void set_greyscale_colormap(void); -void set_hi240_colormap(void); -void unset_colormap(void); -void set_colormap(int reset); -void set_nofb_params(int restore); -void set_raw_fb_params(int restore); -void do_new_fb(int reset_mem); -void free_old_fb(void); -void check_padded_fb(void); -void install_padded_fb(char *geom); -XImage *initialize_xdisplay_fb(void); -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); -int parse_rotate_string(char *str, int *mode); -int scale_round(int len, double fac); -void initialize_screen(int *argc, char **argv, XImage *fb); -void set_vnc_desktop_name(void); -void announce(int lport, int ssl, char *iface); - -char *vnc_reflect_guess(char *str, char **raw_fb_addr); -void vnc_reflect_process_client(void); -rfbBool vnc_reflect_send_pointer(int x, int y, int mask); -rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down); -rfbBool vnc_reflect_send_cuttext(char *str, int len); - -static void debug_colormap(XImage *fb); -static void set_visual(char *str); -static void nofb_hook(rfbClientPtr cl); -static void remove_fake_fb(void); -static void install_fake_fb(int w, int h, int bpp); -static void initialize_snap_fb(void); -XImage *initialize_raw_fb(int); -static void initialize_clipshift(void); -static int wait_until_mapped(Window win); -static void setup_scaling(int *width_in, int *height_in); - -static void check_filexfer(void); -static void record_last_fb_update(void); -static void check_cursor_changes(void); -static int choose_delay(double dt); - -int rawfb_reset = -1; -int rawfb_dev_video = 0; -int rawfb_vnc_reflect = 0; - -/* - * X11 and rfb display/screen related routines - */ - -/* - * Some handling of 8bpp PseudoColor colormaps. Called for initializing - * the clients and dynamically if -flashcmap is specified. - */ -#define NCOLOR 256 - -/* this is only for rawfb */ -void set_greyscale_colormap(void) { - int i; - if (! screen) { - return; - } - /* mutex */ - if (screen->colourMap.data.shorts) { - free(screen->colourMap.data.shorts); - screen->colourMap.data.shorts = NULL; - } - -if (0) fprintf(stderr, "set_greyscale_colormap: %s\n", raw_fb_pixfmt); - screen->colourMap.count = NCOLOR; - screen->serverFormat.trueColour = FALSE; - screen->colourMap.is16 = TRUE; - screen->colourMap.data.shorts = (unsigned short *) - malloc(3*sizeof(unsigned short) * NCOLOR); - - for(i = 0; i < NCOLOR; i++) { - unsigned short lvl = i * 256; - - screen->colourMap.data.shorts[i*3+0] = lvl; - screen->colourMap.data.shorts[i*3+1] = lvl; - screen->colourMap.data.shorts[i*3+2] = lvl; - } - - rfbSetClientColourMaps(screen, 0, NCOLOR); -} - -/* this is specific to bttv rf tuner card */ -void set_hi240_colormap(void) { - int i; - if (! screen) { - return; - } - /* mutex */ -if (0) fprintf(stderr, "set_hi240_colormap: %s\n", raw_fb_pixfmt); - if (screen->colourMap.data.shorts) { - free(screen->colourMap.data.shorts); - screen->colourMap.data.shorts = NULL; - } - - screen->colourMap.count = 256; - screen->serverFormat.trueColour = FALSE; - screen->colourMap.is16 = TRUE; - screen->colourMap.data.shorts = (unsigned short *) - calloc(3*sizeof(unsigned short) * 256, 1); - - for(i = 0; i < 225; i++) { - int r, g, b; - - r = ( (i/5) % 5 ) * 255.0 / 4 + 0.5; - g = ( (i/25) ) * 255.0 / 8 + 0.5; - b = ( i % 5 ) * 255.0 / 4 + 0.5; - - screen->colourMap.data.shorts[(i+16)*3+0] = (unsigned short) (r * 256); - screen->colourMap.data.shorts[(i+16)*3+1] = (unsigned short) (g * 256); - screen->colourMap.data.shorts[(i+16)*3+2] = (unsigned short) (b * 256); - } - - rfbSetClientColourMaps(screen, 0, 256); -} - -/* this is only for rawfb */ -void unset_colormap(void) { - if (! screen) { - return; - } - if (screen->colourMap.data.shorts) { - free(screen->colourMap.data.shorts); - screen->colourMap.data.shorts = NULL; - } - screen->serverFormat.trueColour = TRUE; -if (0) fprintf(stderr, "unset_colormap: %s\n", raw_fb_pixfmt); -} - -/* this is X11 case */ -void set_colormap(int reset) { - -#if NO_X11 - if (!reset) {} - return; -#else - static int init = 1; - static XColor *color = NULL, *prev = NULL; - static int ncolor = 0; - Colormap cmap; - Visual *vis; - int i, ncells, diffs = 0; - - if (reset) { - init = 1; - ncolor = 0; - /* mutex */ - if (screen->colourMap.data.shorts) { - free(screen->colourMap.data.shorts); - screen->colourMap.data.shorts = NULL; - } - if (color) { - free(color); - color = NULL; - } - if (prev) { - free(prev); - prev = NULL; - } - } - - if (init) { - if (depth > 16) { - ncolor = NCOLOR; - } else if (depth > 8) { - ncolor = 1 << depth; - } else { - ncolor = NCOLOR; - } - /* mutex */ - screen->colourMap.count = ncolor; - screen->serverFormat.trueColour = FALSE; - screen->colourMap.is16 = TRUE; - screen->colourMap.data.shorts = (unsigned short *) - malloc(3*sizeof(unsigned short) * ncolor); - } - if (color == NULL) { - color = (XColor *) calloc(ncolor * sizeof(XColor), 1); - prev = (XColor *) calloc(ncolor * sizeof(XColor), 1); - } - - for (i=0; i < ncolor; i++) { - prev[i].red = color[i].red; - prev[i].green = color[i].green; - prev[i].blue = color[i].blue; - } - - RAWFB_RET_VOID - - X_LOCK; - - cmap = DefaultColormap(dpy, scr); - ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); - vis = default_visual; - - if (subwin) { - XWindowAttributes attr; - - if (XGetWindowAttributes(dpy, window, &attr)) { - cmap = attr.colormap; - vis = attr.visual; - ncells = vis->map_entries; - } - } - - if (ncells != ncolor) { - if (! shift_cmap) { - screen->colourMap.count = ncells; - } - } - if (init && ! quiet) { - rfbLog("set_colormap: number of cells: %d, " - "ncolor(%d) is %d.\n", ncells, depth, ncolor); - } - - if (flash_cmap && ! init) { - XWindowAttributes attr; - Window c; - int tries = 0; - - c = window; - while (c && tries++ < 16) { - c = query_pointer(c); - if (valid_window(c, &attr, 0)) { - if (attr.colormap && attr.map_installed) { - cmap = attr.colormap; - vis = attr.visual; - ncells = vis->map_entries; - break; - } - } else { - break; - } - } - } - if (ncells > ncolor && ! quiet) { - rfbLog("set_colormap: big problem: ncells=%d > %d\n", - ncells, ncolor); - } - - if (vis->class == TrueColor || vis->class == DirectColor) { - /* - * Kludge to make 8bpp TrueColor & DirectColor be like - * the StaticColor map. The ncells = 8 is "8 per subfield" - * mentioned in xdpyinfo. Looks OK... perhaps fortuitously. - */ - if (ncells == 8 && ! shift_cmap) { - ncells = ncolor; - } - } - - for (i=0; i < ncells; i++) { - color[i].pixel = i; - color[i].pad = 0; - } - - XQueryColors(dpy, cmap, color, ncells); - - X_UNLOCK; - - for(i = ncells - 1; i >= 0; i--) { - int k = i + shift_cmap; - - screen->colourMap.data.shorts[i*3+0] = color[i].red; - screen->colourMap.data.shorts[i*3+1] = color[i].green; - screen->colourMap.data.shorts[i*3+2] = color[i].blue; - - if (prev[i].red != color[i].red || - prev[i].green != color[i].green || - prev[i].blue != color[i].blue ) { - diffs++; - } - - if (shift_cmap && k >= 0 && k < ncolor) { - /* kludge to copy the colors to higher pixel values */ - screen->colourMap.data.shorts[k*3+0] = color[i].red; - screen->colourMap.data.shorts[k*3+1] = color[i].green; - screen->colourMap.data.shorts[k*3+2] = color[i].blue; - } - } - - if (diffs && ! init) { - if (! all_clients_initialized()) { - rfbLog("set_colormap: warning: sending cmap " - "with uninitialized clients.\n"); - } - if (shift_cmap) { - rfbSetClientColourMaps(screen, 0, ncolor); - } else { - rfbSetClientColourMaps(screen, 0, ncells); - } - } - - init = 0; -#endif /* NO_X11 */ -} - -static void debug_colormap(XImage *fb) { - static int debug_cmap = -1; - int i, k, *histo; - int ncolor; - - if (debug_cmap < 0) { - if (getenv("DEBUG_CMAP") != NULL) { - debug_cmap = 1; - } else { - debug_cmap = 0; - } - } - if (! debug_cmap) { - return; - } - if (! fb) { - return; - } - if (fb->bits_per_pixel > 16) { - return; - } - ncolor = screen->colourMap.count; - histo = (int *) calloc(ncolor * sizeof(int), 1); - - for (i=0; i < ncolor; i++) { - histo[i] = 0; - } - for (k = 0; k < fb->width * fb->height; k++) { - unsigned char n; - char c = *(fb->data + k); - - n = (unsigned char) c; - histo[n]++; - } - fprintf(stderr, "\nColormap histogram for current screen contents:\n"); - for (i=0; i < ncolor; i++) { - unsigned short r = screen->colourMap.data.shorts[i*3+0]; - unsigned short g = screen->colourMap.data.shorts[i*3+1]; - unsigned short b = screen->colourMap.data.shorts[i*3+2]; - - fprintf(stderr, " %03d: %7d %04x/%04x/%04x", i, histo[i], - r, g, b); - if ((i+1) % 2 == 0) { - fprintf(stderr, "\n"); - } - } - free(histo); - fprintf(stderr, "\n"); -} - -/* - * Experimental mode to force the visual of the window instead of querying - * it. Used for testing, overriding some rare cases (win2vnc), and for - * -overlay . Input string can be a decimal or 0x hex or something like - * TrueColor or TrueColor:24 to force a depth as well. - * - * visual_id and possibly visual_depth are set. - */ -static void set_visual(char *str) { -#if NO_X11 - RAWFB_RET_VOID - if (!str) {} - return; -#else - int vis, vdepth, defdepth; - XVisualInfo vinfo; - char *p, *vstring = strdup(str); - - RAWFB_RET_VOID - - defdepth = DefaultDepth(dpy, scr); - visual_id = (VisualID) 0; - visual_depth = 0; - - if (!strcmp(vstring, "ignore") || !strcmp(vstring, "default") - || !strcmp(vstring, "")) { - free(vstring); - return; - } - - /* set visual depth */ - if ((p = strchr(vstring, ':')) != NULL) { - visual_depth = atoi(p+1); - *p = '\0'; - vdepth = visual_depth; - } else { - vdepth = defdepth; - } - if (! quiet) { - fprintf(stderr, "\nVisual Info:\n"); - fprintf(stderr, " set_visual(\"%s\")\n", str); - fprintf(stderr, " visual_depth: %d\n", vdepth); - } - - /* set visual id number */ - if (strcmp(vstring, "StaticGray") == 0) { - vis = StaticGray; - } else if (strcmp(vstring, "GrayScale") == 0) { - vis = GrayScale; - } else if (strcmp(vstring, "StaticColor") == 0) { - vis = StaticColor; - } else if (strcmp(vstring, "PseudoColor") == 0) { - vis = PseudoColor; - } else if (strcmp(vstring, "TrueColor") == 0) { - vis = TrueColor; - } else if (strcmp(vstring, "DirectColor") == 0) { - vis = DirectColor; - } else { - unsigned int v_in; - if (sscanf(vstring, "0x%x", &v_in) != 1) { - if (sscanf(vstring, "%u", &v_in) == 1) { - visual_id = (VisualID) v_in; - return; - } - rfbLogEnable(1); - rfbLog("invalid -visual arg: %s\n", vstring); - X_UNLOCK; - clean_up_exit(1); - } - visual_id = (VisualID) v_in; - free(vstring); - return; - } - - if (! quiet) fprintf(stderr, " visual: %d\n", vis); - if (XMatchVisualInfo(dpy, scr, visual_depth, vis, &vinfo)) { - ; - } else if (XMatchVisualInfo(dpy, scr, defdepth, vis, &vinfo)) { - ; - } else { - rfbLogEnable(1); - rfbLog("could not find visual: %s\n", vstring); - X_UNLOCK; - clean_up_exit(1); - } - free(vstring); - - /* set numerical visual id. */ - visual_id = vinfo.visualid; -#endif /* NO_X11 */ -} - -void set_nofb_params(int restore) { - static int first = 1; - static int save[100]; - static char *scroll = NULL; - int i = 0; - - if (first) { - first = 0; - save[i++] = use_xfixes; - save[i++] = use_xdamage; - save[i++] = use_xrecord; - save[i++] = wireframe; - save[i++] = use_solid_bg; - save[i++] = overlay; - save[i++] = overlay_cursor; - save[i++] = using_shm; - save[i++] = single_copytile; - save[i++] = take_naps; - save[i++] = measure_speeds; - save[i++] = grab_buster; - save[i++] = show_cursor; - save[i++] = cursor_shape_updates; - save[i++] = cursor_pos_updates; - save[i++] = ncache; - - scroll = scroll_copyrect; - } - if (restore) { - i = 0; - use_xfixes = save[i++]; - use_xdamage = save[i++]; - use_xrecord = save[i++]; - wireframe = save[i++]; - use_solid_bg = save[i++]; - overlay = save[i++]; - overlay_cursor = save[i++]; - using_shm = save[i++]; - single_copytile = save[i++]; - take_naps = save[i++]; - measure_speeds = save[i++]; - grab_buster = save[i++]; - show_cursor = save[i++]; - cursor_shape_updates = save[i++]; - cursor_pos_updates = save[i++]; - ncache = save[i++]; - - scroll_copyrect = scroll; - - if (cursor_shape_updates) { - restore_cursor_shape_updates(screen); - } - initialize_cursors_mode(); - - return; - } - - use_xfixes = 0; - use_xdamage = 0; - use_xrecord = 0; - wireframe = 0; - - use_solid_bg = 0; - overlay = 0; - overlay_cursor = 0; - - using_shm = 0; - single_copytile = 1; - - take_naps = 0; - measure_speeds = 0; - - /* got_grab_buster? */ - grab_buster = 0; - - show_cursor = 0; - show_multiple_cursors = 0; - cursor_shape_updates = 0; - if (! got_cursorpos) { - cursor_pos_updates = 0; - } - - ncache = 0; - - scroll_copyrect = "never"; - - if (! quiet) { - rfbLog("disabling: xfixes, xdamage, solid, overlay, shm,\n"); - rfbLog(" wireframe, scrollcopyrect, ncache,\n"); - rfbLog(" noonetile, nap, cursor, %scursorshape\n", - got_cursorpos ? "" : "cursorpos, " ); - rfbLog(" in -nofb mode.\n"); - } -} - -static char *raw_fb_orig_dpy = NULL; - -void set_raw_fb_params(int restore) { - static int first = 1; - static int vo0, us0, sm0, ws0, wp0, wc0, wb0, na0, tn0; - static int xr0, xrm0, sb0, re0; - static char *mc0; - - /* - * set turn off a bunch of parameters not compatible with - * -rawfb mode: 1) ignoring the X server 2) ignoring user input. - */ - - if (first) { - /* at least save the initial settings... */ - vo0 = view_only; - ws0 = watch_selection; - wp0 = watch_primary; - wc0 = watch_clipboard; - wb0 = watch_bell; - na0 = no_autorepeat; - sb0 = use_solid_bg; - - us0 = use_snapfb; - sm0 = using_shm; - tn0 = take_naps; - xr0 = xrandr; - xrm0 = xrandr_maybe; - re0 = noxrecord; - mc0 = multiple_cursors_mode; - - first = 0; - } - - if (restore) { - view_only = vo0; - watch_selection = ws0; - watch_primary = wp0; - watch_clipboard = wc0; - watch_bell = wb0; - no_autorepeat = na0; - use_solid_bg = sb0; - - use_snapfb = us0; - using_shm = sm0; - take_naps = tn0; - xrandr = xr0; - xrandr_maybe = xrm0; - noxrecord = re0; - multiple_cursors_mode = mc0; - - if (! dpy && raw_fb_orig_dpy) { - dpy = XOpenDisplay_wr(raw_fb_orig_dpy); - last_open_xdisplay = time(NULL); - if (dpy) { - if (! quiet) rfbLog("reopened DISPLAY: %s\n", - raw_fb_orig_dpy); - scr = DefaultScreen(dpy); - rootwin = RootWindow(dpy, scr); - check_xevents(1); - } else { - if (! quiet) rfbLog("WARNING: failed to reopen " - "DISPLAY: %s\n", raw_fb_orig_dpy); - } - } - return; - } - - if (verbose) { - rfbLog("set_raw_fb_params: modifying settings for " - "-rawfb mode.\n"); - } - - if (got_noviewonly) { - /* - * The user input parameters are not unset under - * -noviewonly... this usage should be very rare - * (i.e. rawfb but also send user input to the X - * display, most likely using /dev/fb0 for some reason...) - */ - if (verbose) { - rfbLog("rawfb: -noviewonly mode: still sending mouse and\n"); - rfbLog("rawfb: keyboard input to the X DISPLAY!!\n"); - } - } else { - /* Normal case: */ -#if 0 - if (! view_only && ! pipeinput_str) { - if (! quiet) rfbLog(" rawfb: setting view_only\n"); - view_only = 1; - } -#endif - if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) { - ; - } else if (watch_selection) { - if (verbose) rfbLog(" rawfb: turning off " - "watch_selection\n"); - watch_selection = 0; - } - if (watch_primary) { - if (verbose) rfbLog(" rawfb: turning off " - "watch_primary\n"); - watch_primary = 0; - } - if (watch_clipboard) { - if (verbose) rfbLog(" rawfb: turning off " - "watch_clipboard\n"); - watch_clipboard = 0; - } - if (watch_bell) { - if (verbose) rfbLog(" rawfb: turning off watch_bell\n"); - watch_bell = 0; - } - if (no_autorepeat) { - if (verbose) rfbLog(" rawfb: turning off " - "no_autorepeat\n"); - no_autorepeat = 0; - } - if (use_solid_bg) { - if (verbose) rfbLog(" rawfb: turning off " - "use_solid_bg\n"); - use_solid_bg = 0; - } -#ifndef MACOSX - if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) { - ; - } else { - multiple_cursors_mode = strdup("arrow"); - } -#endif - } - if (using_shm) { - if (verbose) rfbLog(" rawfb: turning off using_shm\n"); - using_shm = 0; - } - if (take_naps) { - if (verbose) rfbLog(" rawfb: turning off take_naps\n"); - take_naps = 0; - } - if (xrandr) { - if (verbose) rfbLog(" rawfb: turning off xrandr\n"); - xrandr = 0; - } - if (xrandr_maybe) { - if (verbose) rfbLog(" rawfb: turning off xrandr_maybe\n"); - xrandr_maybe = 0; - } - if (! noxrecord) { - if (verbose) rfbLog(" rawfb: turning off xrecord\n"); - noxrecord = 1; - } -} - -/* - * Presumably under -nofb the clients will never request the framebuffer. - * However, we have gotten such a request... so let's just give them - * the current view on the display. n.b. x2vnc and perhaps win2vnc - * requests a 1x1 pixel for some workaround so sadly this evidently - * nearly always happens. - */ -static void nofb_hook(rfbClientPtr cl) { - XImage *fb; - XImage raw; - - rfbLog("framebuffer requested in -nofb mode by client %s\n", cl->host); - /* ignore xrandr */ - - if (raw_fb && ! dpy) { - fb = &raw; - fb->data = (char *)malloc(32); - } else { - int use_real_ximage = 0; - if (use_real_ximage) { - fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap); - } else { - fb = &raw; - fb->data = (char *) calloc(dpy_x*dpy_y*bpp/8, 1); - } - } - main_fb = fb->data; - rfb_fb = main_fb; - /* mutex */ - screen->frameBuffer = rfb_fb; - screen->displayHook = NULL; -} - -void free_old_fb(void) { - char *fbs[16]; - int i, j, nfb = 0, db = 0; - - fbs[nfb++] = main_fb; main_fb = NULL; - fbs[nfb++] = rfb_fb; rfb_fb = NULL; - fbs[nfb++] = cmap8to24_fb; cmap8to24_fb = NULL; - fbs[nfb++] = snap_fb; snap_fb = NULL; - fbs[nfb++] = rot_fb; rot_fb = NULL; - fbs[nfb++] = raw_fb; raw_fb = NULL; - - for (i=0; i < nfb; i++) { - char *fb = fbs[i]; - int freeit = 1; - if (! fb || fb < (char *) 0x10) { - continue; - } - for (j=0; j < i; j++) { - if (fb == fbs[j]) { - freeit = 0; - break; - } - } - if (freeit) { - if (db) fprintf(stderr, "free: %i %p\n", i, fb); - free(fb); - } else { - if (db) fprintf(stderr, "skip: %i %p\n", i, fb); - } - } -} - -static char _lcs_tmp[128]; -static int _bytes0_size = 128, _bytes0[128]; - -static char *lcs(rfbClientPtr cl) { - sprintf(_lcs_tmp, "%d/%d/%d/%d/%d-%d/%d/%d", - !!(cl->newFBSizePending), - !!(cl->cursorWasChanged), - !!(cl->cursorWasMoved), - !!(cl->reverseConnection), - cl->state, - cl->modifiedRegion ? !!(sraRgnEmpty(cl->modifiedRegion)) : 2, - cl->requestedRegion ? !!(sraRgnEmpty(cl->requestedRegion)) : 2, - cl->copyRegion ? !!(sraRgnEmpty(cl->copyRegion)) : 2 - ); - return _lcs_tmp; -} - -static int lock_client_sends(int lock) { - static rfbClientPtr *cls = NULL; - static int cls_len = 0; - static int blocked = 0; - static int state = 0; - rfbClientIteratorPtr iter; - rfbClientPtr cl; - char *s; - - if (!use_threads || !screen) { - return 0; - } - if (lock < 0) { - return state; - } - state = lock; - - if (lock) { - if (cls_len < client_count + 128) { - if (cls != NULL) { - free(cls); - } - cls_len = client_count + 256; - cls = (rfbClientPtr *) calloc(cls_len * sizeof(rfbClientPtr), 1); - } - - iter = rfbGetClientIterator(screen); - blocked = 0; - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - s = lcs(cl); - SEND_LOCK(cl); - rfbLog("locked client: %p %.6f %s\n", cl, dnowx(), s); - cls[blocked++] = cl; - } - rfbReleaseClientIterator(iter); - } else { - int i; - for (i=0; i < blocked; i++) { - cl = cls[i]; - if (cl != NULL) { - s = lcs(cl); - SEND_UNLOCK(cl) - rfbLog("unlocked client: %p %.6f %s\n", cl, dnowx(), s); - } - cls[i] = NULL; - } - blocked = 0; - } - return state; -} - -static void settle_clients(int init) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int fb_pend, i, ms = 1000; - char *s; - - if (!use_threads || !screen) { - return; - } - - if (init) { - iter = rfbGetClientIterator(screen); - i = 0; - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - if (i < _bytes0_size) { - _bytes0[i] = rfbStatGetSentBytesIfRaw(cl); - } - i++; - } - rfbReleaseClientIterator(iter); - - if (getenv("X11VNC_THREADS_NEW_FB_SLEEP")) { - ms = atoi(getenv("X11VNC_THREADS_NEW_FB_SLEEP")); - } else if (subwin) { - ms = 250; - } else { - ms = 500; - } - usleep(ms * 1000); - return; - } - - if (getenv("X11VNC_THREADS_NEW_FB_SLEEP")) { - ms = atoi(getenv("X11VNC_THREADS_NEW_FB_SLEEP")); - } else if (subwin) { - ms = 500; - } else { - ms = 1000; - } - usleep(ms * 1000); - - for (i=0; i < 5; i++) { - fb_pend = 0; - iter = rfbGetClientIterator(screen); - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - s = lcs(cl); - if (cl->newFBSizePending) { - fb_pend++; - rfbLog("pending fb size: %p %.6f %s\n", cl, dnowx(), s); - } - } - rfbReleaseClientIterator(iter); - if (fb_pend > 0) { - rfbLog("do_new_fb: newFBSizePending extra -threads sleep (%d)\n", i+1); - usleep(ms * 1000); - } else { - break; - } - } - for (i=0; i < 5; i++) { - int stuck = 0, tot = 0, j = 0; - iter = rfbGetClientIterator(screen); - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - if (j < _bytes0_size) { - int db = rfbStatGetSentBytesIfRaw(cl) - _bytes0[j]; - int Bpp = cl->format.bitsPerPixel / 8; - - s = lcs(cl); - rfbLog("addl bytes sent: %p %.6f %s %d %d\n", - cl, dnowx(), s, db, _bytes0[j]); - - if (i==0) { - if (db < Bpp * dpy_x * dpy_y) { - stuck++; - } - } else if (i==1) { - if (db < 0.5 * Bpp * dpy_x * dpy_y) { - stuck++; - } - } else { - if (db <= 0) { - stuck++; - } - } - } - tot++; - j++; - } - rfbReleaseClientIterator(iter); - if (stuck > 0) { - rfbLog("clients stuck: %d/%d sleep(%d)\n", stuck, tot, i); - usleep(2 * ms * 1000); - } else { - break; - } - } -} - -static void prep_clients_for_new_fb(void) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - - if (!use_threads || !screen) { - return; - } - iter = rfbGetClientIterator(screen); - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - if (!cl->newFBSizePending) { - rfbLog("** set_new_fb_size_pending client: %p\n", cl); - cl->newFBSizePending = TRUE; - } - cl->cursorWasChanged = FALSE; - cl->cursorWasMoved = FALSE; - } - rfbReleaseClientIterator(iter); -} - -void do_new_fb(int reset_mem) { - XImage *fb; - - /* for threaded we really should lock libvncserver out. */ - if (use_threads) { - int ms = 1000; - if (getenv("X11VNC_THREADS_NEW_FB_SLEEP")) { - ms = atoi(getenv("X11VNC_THREADS_NEW_FB_SLEEP")); - } else if (subwin) { - ms = 500; - } else { - ms = 1000; - } - rfbLog("Warning: changing framebuffers in threaded mode may be unstable.\n"); - threads_drop_input = 1; - usleep(ms * 1000); - } - - INPUT_LOCK; - lock_client_sends(1); - - if (use_threads) { - settle_clients(1); - } - -#ifdef MACOSX - if (macosx_console) { - macosxCG_fini(); - } -#endif - if (reset_mem == 1) { - /* reset_mem == 2 is a hack for changing users... */ - clean_shm(0); - free_tiles(); - } - - free_old_fb(); - - fb = initialize_xdisplay_fb(); - - initialize_screen(NULL, NULL, fb); - - if (reset_mem) { - initialize_tiles(); - initialize_blackouts_and_xinerama(); - initialize_polling_images(); - } - if (ncache) { - check_ncache(1, 0); - } - - prep_clients_for_new_fb(); - lock_client_sends(0); - INPUT_UNLOCK; - - if (use_threads) { - /* need to let things settle... */ - settle_clients(0); - threads_drop_input = 0; - } -} - -static void remove_fake_fb(void) { - if (! screen) { - return; - } - rfbLog("removing fake fb: 0x%x\n", fake_fb); - - do_new_fb(1); - - /* - * fake_fb is freed in do_new_fb(), but we set to NULL here to - * indicate it is gone. - */ - fake_fb = NULL; -} - -static void rfb_new_framebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer, - int width,int height, int bitsPerSample,int samplesPerPixel, - int bytesPerPixel) { - - rfbNewFramebuffer(rfbScreen, framebuffer, width, height, bitsPerSample, - samplesPerPixel, bytesPerPixel); - -} - -static void install_fake_fb(int w, int h, int bpp) { - int bpc; - if (! screen) { - return; - } - lock_client_sends(1); - if (fake_fb) { - free(fake_fb); - } - fake_fb = (char *) calloc(w*h*bpp/8, 1); - if (! fake_fb) { - rfbLog("could not create fake fb: %dx%d %d\n", w, h, bpp); - lock_client_sends(0); - return; - } - bpc = guess_bits_per_color(bpp); - rfbLog("installing fake fb: %dx%d %d\n", w, h, bpp); - rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n", - screen, fake_fb, w, h, bpc, 1, bpp/8); - - rfb_new_framebuffer(screen, fake_fb, w, h, bpc, 1, bpp/8); - lock_client_sends(0); -} - -void check_padded_fb(void) { - if (! fake_fb) { - return; - } - if (unixpw_in_progress) return; - - if (time(NULL) > pad_geometry_time+1 && all_clients_initialized()) { - remove_fake_fb(); - } -} - -void install_padded_fb(char *geom) { - int w, h; - int ok = 1; - if (! geom || *geom == '\0') { - ok = 0; - } else if (sscanf(geom, "%dx%d", &w, &h) != 2) { - ok = 0; - } - w = nabs(w); - h = nabs(h); - - if (w < 5) w = 5; - if (h < 5) h = 5; - - if (!ok) { - rfbLog("skipping invalid pad geometry: '%s'\n", NONUL(geom)); - return; - } - install_fake_fb(w, h, bpp); - pad_geometry_time = time(NULL); -} - -static void initialize_snap_fb(void) { - RAWFB_RET_VOID - if (snap_fb) { - free(snap_fb); - } - snap = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, - ZPixmap); - snap_fb = snap->data; -} - -static rfbClient* client = NULL; - -void vnc_reflect_bell(rfbClient *cl) { - if (cl) {} - if (sound_bell) { - if (unixpw_in_progress) { - return; - } - if (! all_clients_initialized()) { - rfbLog("vnc_reflect_bell: not sending bell: " - "uninitialized clients\n"); - } else { - if (screen && client_count) { - rfbSendBell(screen); - } - } - } -} - -void vnc_reflect_recv_cuttext(rfbClient *cl, const char *str, int len) { - if (cl) {} - if (unixpw_in_progress) { - return; - } - if (! watch_selection) { - return; - } - if (! all_clients_initialized()) { - rfbLog("vnc_reflect_recv_cuttext: no send: uninitialized clients\n"); - return; /* some clients initializing, cannot send */ - } - rfbSendServerCutText(screen, (char *)str, len); -} - -void vnc_reflect_got_update(rfbClient *cl, int x, int y, int w, int h) { - if (cl) {} - if (use_xdamage) { - static int first = 1; - if (first) { - collect_non_X_xdamage(-1, -1, -1, -1, 0); - first = 0; - } - collect_non_X_xdamage(x, y, w, h, 1); - } -} - -void vnc_reflect_got_cursorshape(rfbClient *cl, int xhot, int yhot, int width, int height, int bytesPerPixel) { - static int serial = 1; - int i, j; - char *pixels = NULL; - unsigned long r, g, b; - unsigned int ui = 0; - unsigned long red_mask, green_mask, blue_mask; - - if (cl) {} - if (unixpw_in_progress) { - return; - } - if (! all_clients_initialized()) { - rfbLog("vnc_reflect_got_copyshape: no send: uninitialized clients\n"); - return; /* some clients initializing, cannot send */ - } - if (! client->rcSource) { - return; - } - if (bytesPerPixel != 1 && bytesPerPixel != 2 && bytesPerPixel != 4) { - return; - } - - red_mask = (client->format.redMax << client->format.redShift); - green_mask = (client->format.greenMax << client->format.greenShift); - blue_mask = (client->format.blueMax << client->format.blueShift); - - pixels = (char *)malloc(4*width*height); - for (j=0; j<height; j++) { - for (i=0; i<width; i++) { - unsigned int* uip; - unsigned char* uic; - int m; - if (bytesPerPixel == 1) { - unsigned char* p = (unsigned char *) client->rcSource; - ui = (unsigned long) *(p + j * width + i); - } else if (bytesPerPixel == 2) { - unsigned short* p = (unsigned short *) client->rcSource; - ui = (unsigned long) *(p + j * width + i); - } else if (bytesPerPixel == 4) { - unsigned int* p = (unsigned int *) client->rcSource; - ui = (unsigned long) *(p + j * width + i); - } - r = (red_mask & ui) >> client->format.redShift; - g = (green_mask & ui) >> client->format.greenShift; - b = (blue_mask & ui) >> client->format.blueShift; - - r = (255 * r) / client->format.redMax; - g = (255 * g) / client->format.greenMax; - b = (255 * b) / client->format.blueMax; - - ui = (r << 16 | g << 8 | b << 0) ; - - uic = (unsigned char *)client->rcMask; - m = (int) *(uic + j * width + i); - if (m) { - ui |= 0xff000000; - } - uip = (unsigned int *)pixels; - *(uip + j * width + i) = ui; - } - } - - store_cursor(serial++, (unsigned long*) pixels, width, height, 32, xhot, yhot); - free(pixels); - set_cursor(cursor_x, cursor_y, get_which_cursor()); -} - -rfbBool vnc_reflect_cursor_pos(rfbClient *cl, int x, int y) { - if (cl) {} - if (debug_pointer) { - rfbLog("vnc_reflect_cursor_pos: %d %d\n", x, y); - } - if (unixpw_in_progress) { - if (debug_pointer) { - rfbLog("vnc_reflect_cursor_pos: unixpw_in_progress%d\n", unixpw_in_progress); - } - return TRUE; - } - if (! all_clients_initialized()) { - rfbLog("vnc_reflect_cursor_pos: no send: uninitialized clients\n"); - return TRUE; /* some clients initializing, cannot send */ - } - - cursor_position(x, y); - set_cursor(x, y, get_which_cursor()); - - return TRUE; -} - -static void from_libvncclient_CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { - int i,j; - -#define COPY_RECT_FROM_RECT(BPP) \ - { \ - uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \ - if (dest_y < src_y) { \ - for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \ - if (dest_x < src_x) { \ - for(i = dest_x; i < dest_x+w; i++) { \ - ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ - } \ - } else { \ - for(i = dest_x+w-1; i >= dest_x; i--) { \ - ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ - } \ - } \ - } \ - } else { \ - for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \ - if (dest_x < src_x) { \ - for(i = dest_x; i < dest_x+w; i++) { \ - ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ - } \ - } else { \ - for(i = dest_x+w-1; i >= dest_x; i--) { \ - ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ - } \ - } \ - } \ - } \ - } - - switch(client->format.bitsPerPixel) { - case 8: COPY_RECT_FROM_RECT(8); break; - case 16: COPY_RECT_FROM_RECT(16); break; - case 32: COPY_RECT_FROM_RECT(32); break; - default: - rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); - } -} - -void vnc_reflect_got_copyrect(rfbClient *cl, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { - sraRegionPtr reg; - int dx, dy, rc = -1; - static int last_dx = 0, last_dy = 0; - if (cl) {} - if (unixpw_in_progress) { - return; - } - if (! all_clients_initialized()) { - rfbLog("vnc_reflect_got_copyrect: no send: uninitialized clients\n"); - return; /* some clients initializing, cannot send */ - } - dx = dest_x - src_x; - dy = dest_y - src_y; - if (dx != last_dx || dy != last_dy) { - rc = fb_push_wait(0.05, FB_COPY|FB_MOD); - } - if (0) fprintf(stderr, "vnc_reflect_got_copyrect: %03dx%03d+%03d+%03d %3d %3d rc=%d\n", dest_x, dest_y, w, h, dx, dy, rc); - reg = sraRgnCreateRect(dest_x, dest_y, dest_x + w, dest_y + h); - do_copyregion(reg, dx, dy, 0); - sraRgnDestroy(reg); - - last_dx = dx; - last_dy = dy; - - from_libvncclient_CopyRectangleFromRectangle(cl, src_x, src_y, w, h, dest_x, dest_y); -} - -rfbBool vnc_reflect_resize(rfbClient *cl) { - static int first = 1; - if(cl->frameBuffer) { - free(cl->frameBuffer); - } - cl->frameBuffer= malloc(cl->width * cl->height * cl->format.bitsPerPixel/8); - rfbLog("vnc_reflect_resize: %dx%dx%d first=%d\n", cl->width, cl->height, - cl->format.bitsPerPixel, first); - if (!first) { - do_new_fb(1); - } - first = 0; - return cl->frameBuffer ? TRUE : FALSE; -} - -#ifdef rfbCredentialTypeX509 -static rfbCredential* vnc_reflect_get_credential(rfbClient* client, int type) { - char *pass = getenv("X11VNC_REFLECT_PASSWORD"); - char *user = getenv("X11VNC_REFLECT_USER"); - char *cert = getenv("X11VNC_REFLECT_CACERT"); - char *ccrl = getenv("X11VNC_REFLECT_CACRL"); - char *clic = getenv("X11VNC_REFLECT_CLIENTCERT"); - char *clik = getenv("X11VNC_REFLECT_CLIENTKEY"); - int db = 0; - if (client) {} -if (db) fprintf(stderr, "type: %d\n", type); -#ifdef rfbCredentialTypeUser - if (type == rfbCredentialTypeUser) { - if (!pass && !user) { - return NULL; - } else { - rfbCredential *rc = (rfbCredential *) calloc(sizeof(rfbCredential), 1); - rc->userCredential.username = (user ? strdup(user) : NULL); - rc->userCredential.password = (pass ? strdup(pass) : NULL); - return rc; - } - } -#endif - if (type == rfbCredentialTypeX509) { -if (db) fprintf(stderr, "cert: %s\n", cert); -if (db) fprintf(stderr, "ccrl: %s\n", ccrl); -if (db) fprintf(stderr, "clic: %s\n", clic); -if (db) fprintf(stderr, "clik: %s\n", clik); - if (!cert && !ccrl && !clic && !clik) { - return NULL; - } else { - rfbCredential *rc = (rfbCredential *) calloc(sizeof(rfbCredential), 1); - rc->x509Credential.x509CACertFile = (cert ? strdup(cert) : NULL); - rc->x509Credential.x509CACrlFile = (ccrl ? strdup(ccrl) : NULL); - rc->x509Credential.x509ClientCertFile = (clic ? strdup(clic) : NULL); - rc->x509Credential.x509ClientKeyFile = (clik ? strdup(clik) : NULL); - return rc; - } - } - return NULL; -} -#endif - -static char* vnc_reflect_get_password(rfbClient* client) { - char *q, *p, *str = getenv("X11VNC_REFLECT_PASSWORD"); - int len = 110; - - if (client) {} - - if (str) { - len += 2*strlen(str); - } - p = (char *) calloc(len, 1); - if (!str || strlen(str) == 0) { - fprintf(stderr, "VNC Reflect Password: "); - fgets(p, 100, stdin); - } else { - if (strstr(str, "file:") == str) { - FILE *f = fopen(str + strlen("file:"), "r"); - if (f) { - fgets(p, 100, f); - fclose(f); - } - } - if (p[0] == '\0') { - strncpy(p, str, 100); - } - } - q = p; - while (*q != '\0') { - if (*q == '\n') { - *q = '\0'; - } - q++; - } - return p; -} - -char *vnc_reflect_guess(char *str, char **raw_fb_addr) { - - static int first = 1; - char *hp = str + strlen("vnc:"); - char *at = NULL; - int argc = 0, i; - char *argv[16]; - char str2[256]; - char *str0 = strdup(str); - - if (client == NULL) { - 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); - - at = strchr(hp, '@'); - if (at) { - *at = '\0'; - at++; - } - - client->appData.useRemoteCursor = TRUE; - client->canHandleNewFBSize = TRUE; - - client->HandleCursorPos = vnc_reflect_cursor_pos; - client->GotFrameBufferUpdate = vnc_reflect_got_update; - client->MallocFrameBuffer = vnc_reflect_resize; - client->Bell = vnc_reflect_bell; -#if 0 - client->SoftCursorLockArea = NULL; - client->SoftCursorUnlockScreen = NULL; - client->FinishedFrameBufferUpdate = NULL; - client->HandleKeyboardLedState = NULL; - client->HandleTextChat = NULL; -#endif - client->GotXCutText = vnc_reflect_recv_cuttext; - client->GotCursorShape = vnc_reflect_got_cursorshape; - client->GotCopyRect = vnc_reflect_got_copyrect; - - if (getenv("X11VNC_REFLECT_PASSWORD")) { - client->GetPassword = vnc_reflect_get_password; - } -#ifdef rfbCredentialTypeX509 - client->GetCredential = NULL; - if (0 || getenv("LIBVNCCLIENT_GET_CREDENTIAL")) { - client->GetCredential = vnc_reflect_get_credential; - } -#endif - - if (first) { - argv[argc++] = "x11vnc_rawfb_vnc"; - if (strstr(hp, "listen") == hp) { - char *q = strrchr(hp, ':'); - argv[argc++] = strdup("-listen"); - if (q) { - client->listenPort = atoi(q+1); - } else { - client->listenPort = LISTEN_PORT_OFFSET; - } - } else { - argv[argc++] = strdup(hp); - } - - if (! rfbInitClient(client, &argc, argv)) { - rfbLog("vnc_reflector failed for: %s\n", str0); - clean_up_exit(1); - } - } - - if (at) { - sprintf(str2, "map:/dev/null@%s", at); - } else { - unsigned long red_mask, green_mask, blue_mask; - red_mask = (client->format.redMax << client->format.redShift); - green_mask = (client->format.greenMax << client->format.greenShift); - blue_mask = (client->format.blueMax << client->format.blueShift); - sprintf(str2, "map:/dev/null@%dx%dx%d:0x%lx/0x%lx/0x%lx", - client->width, client->height, client->format.bitsPerPixel, - red_mask, green_mask, blue_mask); - } - *raw_fb_addr = (char *) client->frameBuffer; - free(str0); - - if (first) { - setup_cursors_and_push(); - - for (i=0; i<10; i++) { - vnc_reflect_process_client(); - } - } - first = 0; - - return strdup(str2); -} - -rfbBool vnc_reflect_send_pointer(int x, int y, int mask) { - int rc; - if (mask >= 0) { - got_user_input++; - got_pointer_input++; - last_pointer_time = time(NULL); - } - - if (clipshift) { - x += coff_x; - y += coff_y; - } - - if (cursor_x != x || cursor_y != y) { - last_pointer_motion_time = dnow(); - } - - cursor_x = x; - cursor_y = y; - - /* record the x, y position for the rfb screen as well. */ - cursor_position(x, y); - - /* change the cursor shape if necessary */ - rc = set_cursor(x, y, get_which_cursor()); - cursor_changes += rc; - - return SendPointerEvent(client, x, y, mask); -} - -rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down) { - return SendKeyEvent(client, key, down); -} - -rfbBool vnc_reflect_send_cuttext(char *str, int len) { - return SendClientCutText(client, str, len); -} - -void vnc_reflect_process_client(void) { - int num; - if (client == NULL) { - return; - } - num = WaitForMessage(client, 1000); - if (num > 0) { - if (!HandleRFBServerMessage(client)) { - rfbLog("vnc_reflect_process_client: read failure to server\n"); - shut_down = 1; - } - } -} - -void linux_dev_fb_msg(char* q) { - if (strstr(q, "/dev/fb") && strstr(UT.sysname, "Linux")) { - rfbLog("\n"); - rfbLog("On Linux you may need to load a kernel module to enable\n"); - rfbLog("the framebuffer device /dev/fb*; e.g.:\n"); - rfbLog(" vga=0x303 (and others) kernel boot parameter\n"); - rfbLog(" modprobe uvesafb\n"); - rfbLog(" modprobe radeonfb (card specific)\n"); - rfbLog(" modprobe nvidiafb (card specific, others)\n"); - rfbLog(" modprobe vesafb (?)\n"); - rfbLog(" modprobe vga16fb\n"); - rfbLog("\n"); - rfbLog("You may also need root permission to open /dev/fb*\n"); - rfbLog("and/or /dev/tty*.\n"); - rfbLog("\n"); - } -} - -#define RAWFB_MMAP 1 -#define RAWFB_FILE 2 -#define RAWFB_SHM 3 - -XImage *initialize_raw_fb(int reset) { - char *str, *rstr, *q; - int w, h, b, shmid = 0; - unsigned long rm = 0, gm = 0, bm = 0, tm; - static XImage ximage_struct; /* n.b.: not (XImage *) */ - static XImage ximage_struct_snap; - int closedpy = 1, i, m, db = 0; - int do_macosx = 0; - int do_reflect = 0; - char *unlink_me = NULL; - - static char *last_file = NULL; - static int last_mode = 0; - - if (reset && last_mode) { - int fd; - if (last_mode != RAWFB_MMAP && last_mode != RAWFB_FILE) { - return NULL; - } - if (last_mode == RAWFB_MMAP) { - munmap(raw_fb_addr, raw_fb_mmap); - } - if (raw_fb_fd >= 0) { - close(raw_fb_fd); - } - raw_fb_fd = -1; -if (db) fprintf(stderr, "initialize_raw_fb reset\n"); - - fd = -1; - if (rawfb_dev_video) { - fd = open(last_file, O_RDWR); - } - if (fd < 0) { - fd = open(last_file, O_RDONLY); - } - if (fd < 0) { - rfbLogEnable(1); - rfbLog("failed to rawfb file: %s\n", last_file); - rfbLogPerror("open"); - clean_up_exit(1); - } - raw_fb_fd = fd; - if (last_mode == RAWFB_MMAP) { - raw_fb_addr = mmap(0, raw_fb_mmap, PROT_READ, - MAP_SHARED, fd, 0); - - if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) { - rfbLogEnable(1); - rfbLog("failed to mmap file: %s\n", last_file); - rfbLog(" raw_fb_addr: %p\n", raw_fb_addr); - rfbLogPerror("mmap"); - clean_up_exit(1); - } - } - return NULL; - } - -#ifdef MACOSX - if (raw_fb_addr != NULL && macosx_console && raw_fb_addr == macosx_get_fb_addr()) { - raw_fb_addr = NULL; - } -#endif - - if (raw_fb_addr || raw_fb_seek) { - if (raw_fb_shm) { - shmdt(raw_fb_addr); -#if LIBVNCSERVER_HAVE_MMAP - } else if (raw_fb_mmap) { - munmap(raw_fb_addr, raw_fb_mmap); - if (raw_fb_fd >= 0) { - close(raw_fb_fd); - } - raw_fb_fd = -1; -#endif - } else if (raw_fb_seek) { - if (raw_fb_fd >= 0) { - close(raw_fb_fd); - } - raw_fb_fd = -1; - } - raw_fb_addr = NULL; - raw_fb_mmap = 0; - raw_fb_seek = 0; - } - if (! raw_fb_str) { - return NULL; - } - - if (raw_fb_str[0] == '+') { - rstr = strdup(raw_fb_str+1); - closedpy = 0; - if (! window) { - window = rootwin; - } - } else { - rstr = strdup(raw_fb_str); - } - - /* testing aliases */ - if (!strcasecmp(rstr, "NULL") || !strcasecmp(rstr, "ZERO") - || !strcasecmp(rstr, "NONE")) { - rstr = strdup("map:/dev/zero@640x480x32"); - } else if (!strcasecmp(rstr, "NULLBIG") || !strcasecmp(rstr, "NONEBIG")) { - rstr = strdup("map:/dev/zero@1024x768x32"); - } - if (!strcasecmp(rstr, "RAND")) { - rstr = strdup("file:/dev/urandom@128x128x16"); - } else if (!strcasecmp(rstr, "RANDBIG")) { - rstr = strdup("file:/dev/urandom@640x480x16"); - } else if (!strcasecmp(rstr, "RANDHUGE")) { - rstr = strdup("file:/dev/urandom@1024x768x16"); - } - if (strstr(rstr, "solid=") == rstr) { - char *n = rstr + strlen("solid="); - char tmp[] = "/tmp/rawfb_solid.XXXXXX"; - char str[100]; - unsigned int vals[1024], val; - int x, y, fd, w = 1024, h = 768; - if (strstr(n, "0x")) { - if (sscanf(n, "0x%x", &val) != 1) { - val = 0; - } - } - if (val == 0) { - val = get_pixel(n); - } - if (val == 0) { - val = 0xFF00FF; - } - fd = mkstemp(tmp); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - vals[x] = val; - } - write(fd, (char *)vals, 4 * w); - } - close(fd); - fd = open(tmp, O_WRONLY); - unlink_me = strdup(tmp); - sprintf(str, "map:%s@%dx%dx32", tmp, w, h); - rstr = strdup(str); - } else if (strstr(rstr, "swirl") == rstr) { - char tmp[] = "/tmp/rawfb_swirl.XXXXXX"; - char str[100]; - unsigned int val[1024]; - unsigned int c1, c2, c3, c4; - int x, y, fd, w = 1024, h = 768; - fd = mkstemp(tmp); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - c1 = 0; - c2 = ((x+y)*128)/(w+h); - c3 = (x*128)/w; - c4 = (y*256)/h; - val[x] = (c1 << 24) | (c2 << 16) | (c3 << 8) | (c4 << 0); - } - write(fd, (char *)val, 4 * w); - } - close(fd); - fd = open(tmp, O_WRONLY); - unlink_me = strdup(tmp); - sprintf(str, "map:%s@%dx%dx32", tmp, w, h); - rstr = strdup(str); - } - - - if ( (q = strstr(rstr, "setup:")) == rstr) { - FILE *pipe; - char line[1024], *t; - - set_child_info(); - q += strlen("setup:"); - /* rawfb-setup */ - if (no_external_cmds || !cmd_ok("rawfb-setup")) { - rfbLogEnable(1); - rfbLog("cannot run external commands in -nocmds " - "mode:\n"); - rfbLog(" \"%s\"\n", q); - rfbLog(" exiting.\n"); - clean_up_exit(1); - } - rfbLog("running command to setup rawfb: %s\n", q); - close_exec_fds(); - pipe = popen(q, "r"); - if (! pipe) { - rfbLogEnable(1); - rfbLog("popen of setup command failed.\n"); - rfbLogPerror("popen"); - clean_up_exit(1); - } - line[0] = '\0'; - if (fgets(line, 1024, pipe) == NULL) { - rfbLogEnable(1); - rfbLog("read of setup command failed.\n"); - clean_up_exit(1); - } - pclose(pipe); - str = strdup(line); - t = str; - while (*t != '\0') { - if (*t == '\n') { - *t = '\0'; - } - t++; - } - rfbLog("setup command returned: %s\n", str); - - } else { - str = strdup(rstr); - } - - raw_fb_shm = 0; - raw_fb_mmap = 0; - raw_fb_seek = 0; - raw_fb_fd = -1; - raw_fb_addr = NULL; - raw_fb_offset = 0; - raw_fb_bytes_per_line = 0; - rawfb_vnc_reflect = 0; - - last_mode = 0; - if (last_file) { - free(last_file); - last_file = NULL; - } - if (strstr(str, "Video") == str) { - if (pipeinput_str != NULL) { - free(pipeinput_str); - } - pipeinput_str = strdup("VID"); - initialize_pipeinput(); - str[0] = 'v'; - } - - if (strstr(str, "video") == str || strstr(str, "/dev/video") == str) { - char *str2 = v4l_guess(str, &raw_fb_fd); - if (str2 == NULL) { - rfbLog("v4l_guess failed for: %s\n", str); - clean_up_exit(1); - } - str = str2; - rfbLog("v4l_guess returned: %s\n", str); - rawfb_dev_video = 1; - } else if (strstr(str, "dev/video")) { - rawfb_dev_video = 1; - } else if (strstr(str, "console") == str || strstr(str, "fb") == str || - strstr(str, "/dev/fb") == str || strstr(str, "vt") == str) { - char *str2 = console_guess(str, &raw_fb_fd); - if (str2 == NULL) { - rfbLog("console_guess failed for: %s\n", str); - clean_up_exit(1); - } - str = str2; - rfbLog("console_guess returned: %s\n", str); - } else if (strstr(str, "vnc:") == str) { - char *str2 = vnc_reflect_guess(str, &raw_fb_addr); - - rawfb_vnc_reflect = 1; - do_reflect = 1; - - str = str2; - rfbLog("vnc_reflector set rawfb str to: %s\n", str); - if (pipeinput_str == NULL) { - pipeinput_str = strdup("VNC"); - } - initialize_pipeinput(); - } - - if (closedpy && !view_only && got_noviewonly) { - rfbLog("not closing X DISPLAY under -noviewonly option.\n"); - closedpy = 0; - if (! window) { - window = rootwin; - } - } - - if (! raw_fb_orig_dpy && dpy) { - raw_fb_orig_dpy = strdup(DisplayString(dpy)); - } -#ifndef BOLDLY_CLOSE_DISPLAY -#define BOLDLY_CLOSE_DISPLAY 1 -#endif -#if BOLDLY_CLOSE_DISPLAY - if (closedpy) { - if (dpy) { - rfbLog("closing X DISPLAY: %s in rawfb mode.\n", - DisplayString(dpy)); - XCloseDisplay_wr(dpy); /* yow! */ - } - dpy = NULL; - } -#endif - - /* - * -rawfb shm:163938442@640x480x32:ff/ff00/ff0000+3000 - * -rawfb map:/path/to/file@640x480x32:ff/ff00/ff0000 - * -rawfb file:/path/to/file@640x480x32:ff/ff00/ff0000 - */ - - if (raw_fb_full_str) { - free(raw_fb_full_str); - } - raw_fb_full_str = strdup(str); - - - /* +O offset */ - if ((q = strrchr(str, '+')) != NULL) { - if (sscanf(q, "+%d", &raw_fb_offset) == 1) { - *q = '\0'; - } else { - raw_fb_offset = 0; - } - } - /* :R/G/B masks */ - if ((q = strrchr(str, ':')) != NULL) { - if (sscanf(q, ":%lx/%lx/%lx", &rm, &gm, &bm) == 3) { - *q = '\0'; - } else if (sscanf(q, ":0x%lx/0x%lx/0x%lx", &rm, &gm, &bm)== 3) { - *q = '\0'; - } else if (sscanf(q, ":%lu/%lu/%lu", &rm, &gm, &bm) == 3) { - *q = '\0'; - } else { - rm = 0; - gm = 0; - bm = 0; - } - } - if ((q = strrchr(str, '@')) == NULL) { - rfbLogEnable(1); - rfbLog("invalid rawfb str: %s\n", str); - clean_up_exit(1); - } - - if (strrchr(q, '-')) { - char *q2 = strrchr(q, '-'); - raw_fb_bytes_per_line = atoi(q2+1); - *q2 = '\0'; - } - /* @WxHxB */ - if (sscanf(q, "@%dx%dx%d", &w, &h, &b) != 3) { - rfbLogEnable(1); - rfbLog("invalid rawfb str: %s\n", str); - clean_up_exit(1); - } - *q = '\0'; - - if (rm == 0 && gm == 0 && bm == 0) { - /* guess masks... */ - if (b == 24 || b == 32) { - rm = 0xff0000; - gm = 0x00ff00; - bm = 0x0000ff; - } else if (b == 16) { - rm = 0xf800; - gm = 0x07e0; - bm = 0x001f; - } else if (b == 8) { - rm = 0x07; - gm = 0x38; - bm = 0xc0; - } - } - /* we can fake -flipbyteorder to some degree... */ - if (flip_byte_order) { - if (b == 24 || b == 32) { - tm = rm; - rm = bm; - bm = tm; - } else if (b == 16) { - unsigned short s1, s2; - s1 = (unsigned short) rm; - s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8); - rm = (unsigned long) s2; - s1 = (unsigned short) gm; - s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8); - gm = (unsigned long) s2; - s1 = (unsigned short) bm; - s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8); - bm = (unsigned long) s2; - } - } - - /* native fb stuff for bpp < 8 only */ - raw_fb_native_bpp = b; - raw_fb_native_red_mask = rm; - raw_fb_native_green_mask = gm; - raw_fb_native_blue_mask = bm; - raw_fb_native_red_shift = 100; - raw_fb_native_green_shift = 100; - raw_fb_native_blue_shift = 100; - raw_fb_native_red_max = 1; - raw_fb_native_green_max = 1; - raw_fb_native_blue_max = 1; - m = 1; - for (i=0; i<32; i++) { - if (raw_fb_native_red_mask & m) { - if (raw_fb_native_red_shift == 100) { - raw_fb_native_red_shift = i; - } - raw_fb_native_red_max *= 2; - } - if (raw_fb_native_green_mask & m) { - if (raw_fb_native_green_shift == 100) { - raw_fb_native_green_shift = i; - } - raw_fb_native_green_max *= 2; - } - if (raw_fb_native_blue_mask & m) { - if (raw_fb_native_blue_shift == 100) { - raw_fb_native_blue_shift = i; - } - raw_fb_native_blue_max *= 2; - } - m = m << 1; - } - raw_fb_native_red_max -= 1; - raw_fb_native_green_max -= 1; - raw_fb_native_blue_max -= 1; - - if (b < 8) { - /* e.g. VGA16 */ - rfbLog("raw_fb_native_bpp: %d 0x%02lx 0x%02lx 0x%02lx %d/%d/%d %d/%d/%d\n", raw_fb_native_bpp, - raw_fb_native_red_mask, raw_fb_native_green_mask, raw_fb_native_blue_mask, - raw_fb_native_red_max, raw_fb_native_green_max, raw_fb_native_blue_max, - raw_fb_native_red_shift, raw_fb_native_green_shift, raw_fb_native_blue_shift); - raw_fb_expand_bytes = 1; - b = 8; - rm = 0x07; - gm = 0x38; - bm = 0xc0; - } - /* end of stuff for bpp < 8 */ - - dpy_x = wdpy_x = w; - dpy_y = wdpy_y = h; - off_x = 0; - off_y = 0; - - if (rawfb_dev_video) { - if (b == 24) { - rfbLog("enabling -24to32 for 24bpp video\n"); - xform24to32 = 1; - } else { - if (xform24to32) { - rfbLog("disabling -24to32 for 24bpp video\n"); - } - xform24to32 = 0; - } - } - - if (xform24to32) { - if (b != 24) { - rfbLog("warning: -24to32 mode and bpp=%d\n", b); - } - b = 32; - } - if (strstr(str, "snap:") == str) { - use_snapfb = 1; - str[0] = 'f'; str[1] = 'i'; str[2] = 'l'; str[3] = 'e'; - } - - if (strstr(str, "shm:") != str && strstr(str, "mmap:") != str && - strstr(str, "map:") != str && strstr(str, "file:") != str) { - /* hmmm, not following directions, see if map: applies */ - struct stat sbuf; - if (stat(str, &sbuf) == 0) { - 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); - newstr = (char *) malloc(len); - strcpy(newstr, "map:"); - strcat(newstr, str); - free(str); - str = newstr; - } - } - - if (sscanf(str, "shm:%d", &shmid) == 1) { - /* shm:N */ -#if LIBVNCSERVER_HAVE_XSHM || LIBVNCSERVER_HAVE_SHMAT - raw_fb_addr = (char *) shmat(shmid, 0, SHM_RDONLY); - if (! raw_fb_addr) { - rfbLogEnable(1); - rfbLog("failed to attach to shm: %d, %s\n", shmid, str); - rfbLogPerror("shmat"); - clean_up_exit(1); - } - raw_fb_shm = 1; - rfbLog("rawfb: shm: %d W: %d H: %d B: %d addr: %p\n", - shmid, w, h, b, raw_fb_addr); - last_mode = RAWFB_SHM; -#else - rfbLogEnable(1); - rfbLog("x11vnc was compiled without shm support.\n"); - rfbLogPerror("shmat"); - clean_up_exit(1); -#endif - } else if (strstr(str, "map:") == str || strstr(str, "mmap:") == str - || strstr(str, "file:") == str) { - /* map:/path/... or file:/path */ - int fd, do_mmap = 1, size; - struct stat sbuf; - - if (*str == 'f') { - do_mmap = 0; - } - q = strchr(str, ':'); - q++; - - macosx_console = 0; - if (strstr(q, "macosx:") == q) { - /* mmap:macosx:/dev/null@... */ - q += strlen("macosx:"); - do_macosx = 1; - do_mmap = 0; - macosx_console = 1; - } - - last_file = strdup(q); - - fd = raw_fb_fd; - if (fd < 0 && rawfb_dev_video) { - fd = open(q, O_RDWR); - } - if (fd < 0) { - fd = open(q, O_RDONLY); - } - if (fd < 0) { - rfbLogEnable(1); - rfbLog("failed to open file: %s, %s\n", q, str); - rfbLogPerror("open"); - linux_dev_fb_msg(q); - clean_up_exit(1); - } - raw_fb_fd = fd; - - if (raw_fb_native_bpp < 8) { - size = w*h*raw_fb_native_bpp/8 + raw_fb_offset; - } else if (xform24to32) { - size = w*h*24/8 + raw_fb_offset; - } else { - size = w*h*b/8 + raw_fb_offset; - } - if (fstat(fd, &sbuf) == 0) { - if (S_ISREG(sbuf.st_mode)) { - if (0) size = sbuf.st_size; - } else { - rfbLog("raw fb is non-regular file: %s\n", q); - } - } - - if (do_macosx) { - raw_fb_addr = macosx_get_fb_addr(); - raw_fb_mmap = size; - rfbLog("rawfb: macosx fb: %s\n", q); - rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h, - b, raw_fb_addr, size); - last_mode = 0; - } else if (do_reflect) { - raw_fb_mmap = size; - rfbLog("rawfb: vnc fb: %s\n", q); - rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h, - b, raw_fb_addr, size); - last_mode = 0; - - } else if (do_mmap) { -#if LIBVNCSERVER_HAVE_MMAP - raw_fb_addr = mmap(0, size, PROT_READ, MAP_SHARED, - fd, 0); - - if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) { - rfbLogEnable(1); - rfbLog("failed to mmap file: %s, %s\n", q, str); - rfbLog(" raw_fb_addr: %p\n", raw_fb_addr); - rfbLogPerror("mmap"); - - raw_fb_addr = NULL; - rfbLog("mmap(2) failed, trying slower lseek(2)\n"); - raw_fb_seek = size; - last_mode = RAWFB_FILE; - - } else { - raw_fb_mmap = size; - - rfbLog("rawfb: mmap file: %s\n", q); - rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h, - b, raw_fb_addr, size); - last_mode = RAWFB_MMAP; - } -#else - rfbLog("mmap(2) not supported on system, using" - " slower lseek(2)\n"); - raw_fb_seek = size; - last_mode = RAWFB_FILE; -#endif - } else { - raw_fb_seek = size; - last_mode = RAWFB_FILE; - - rfbLog("rawfb: seek file: %s\n", q); - rfbLog(" W: %d H: %d B: %d sz: %d\n", w, h, b, size); - } - } else { - rfbLogEnable(1); - rfbLog("invalid rawfb str: %s\n", str); - clean_up_exit(1); - } - - if (unlink_me) { - unlink(unlink_me); - } - - if (! raw_fb_image) { - raw_fb_image = &ximage_struct; - } - - initialize_clipshift(); - - if (raw_fb_bytes_per_line == 0) { - raw_fb_bytes_per_line = dpy_x*b/8; - - /* - * Put cases here were we can determine that - * raw_bytes_per_line != dpy_x*b/8 - */ -#ifdef MACOSX - if (do_macosx) { - raw_fb_bytes_per_line = macosxCG_CGDisplayBytesPerRow(); - } -#endif - } - - raw_fb_image->bytes_per_line = dpy_x * b/8; - raw_fb = (char *) malloc(dpy_y * dpy_x * b/8); - raw_fb_image->data = raw_fb; - raw_fb_image->format = ZPixmap; - raw_fb_image->width = dpy_x; - raw_fb_image->height = dpy_y; - raw_fb_image->bits_per_pixel = b; - raw_fb_image->bitmap_unit = -1; - - - if (use_snapfb && (raw_fb_seek || raw_fb_mmap)) { - int b_use = b; - if (snap_fb) { - free(snap_fb); - } - if (b_use == 32 && xform24to32) { - /* - * The actual framebuffer (e.g. mapped addr) and - * snap fb must be the same bpp. E.g. both 24bpp. - * Reading FROM snap to utility image will be - * transformed 24->32 in copy_raw_fb_24_to_32. - * - * addr -> snap -> (scanline, fullscreen, ...) - */ - b_use = 24; - raw_fb_bytes_per_line = dpy_x * b_use/8; - } - snap_fb = (char *) malloc(dpy_y * dpy_x * b_use/8); - snap = &ximage_struct_snap; - snap->data = snap_fb; - snap->format = ZPixmap; - snap->width = dpy_x; - snap->height = dpy_y; - snap->bits_per_pixel = b_use; - snap->bytes_per_line = dpy_x * b_use/8; - snap->bitmap_unit = -1; - } - - - raw_fb_image->red_mask = rm; - raw_fb_image->green_mask = gm; - raw_fb_image->blue_mask = bm; - - raw_fb_image->depth = 0; - m = 1; - for (i=0; i<32; i++) { - if (rm & m) { - raw_fb_image->depth++; - } - if (gm & m) { - raw_fb_image->depth++; - } - if (bm & m) { - raw_fb_image->depth++; - } - m = m << 1; - } - if (raw_fb_native_bpp < 8) { - raw_fb_image->depth = raw_fb_expand_bytes * 8; - } - if (! raw_fb_image->depth) { - raw_fb_image->depth = (b == 32) ? 24 : b; - } - - depth = raw_fb_image->depth; - - if (raw_fb_image->depth == 15) { - /* unresolved bug with RGB555... */ - depth++; - } - - if (clipshift || raw_fb_native_bpp < 8) { - memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line); - } else if (raw_fb_addr && ! xform24to32) { - memcpy(raw_fb, raw_fb_addr + raw_fb_offset, dpy_y * raw_fb_image->bytes_per_line); - } else { - memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line); - } - - if (verbose) { - rfbLog("\n"); - rfbLog("rawfb: raw_fb %p\n", raw_fb); - rfbLog(" format %d\n", raw_fb_image->format); - rfbLog(" width %d\n", raw_fb_image->width); - rfbLog(" height %d\n", raw_fb_image->height); - rfbLog(" bpp %d\n", raw_fb_image->bits_per_pixel); - rfbLog(" depth %d\n", raw_fb_image->depth); - rfbLog(" bpl %d\n", raw_fb_image->bytes_per_line); - if (use_snapfb && snap_fb) { - rfbLog(" snap_fb %p\n", snap_fb); - } - } - - free(str); - - return raw_fb_image; -} - -static void initialize_clipshift(void) { - clipshift = 0; - cdpy_x = cdpy_y = coff_x = coff_y = 0; - if (clip_str) { - int w, h, x, y, bad = 0; - if (parse_geom(clip_str, &w, &h, &x, &y, wdpy_x, wdpy_y)) { - if (x < 0) { - x = 0; - } - if (y < 0) { - y = 0; - } - if (x + w > wdpy_x) { - w = wdpy_x - x; - } - if (y + h > wdpy_y) { - h = wdpy_y - y; - } - if (w <= 0 || h <= 0) { - bad = 1; - } - } else { - bad = 1; - } - if (bad) { - rfbLog("*** ignoring invalid -clip WxH+X+Y: %s\n", - clip_str); - } else { - /* OK, change geom behind everyone's back... */ - cdpy_x = w; - cdpy_y = h; - coff_x = x; - coff_y = y; - - clipshift = 1; - - dpy_x = cdpy_x; - dpy_y = cdpy_y; - } - } -} - -static int wait_until_mapped(Window win) { -#if NO_X11 - if (!win) {} - return 0; -#else - int ms = 50, waittime = 30; - time_t start = time(NULL); - XWindowAttributes attr; - - while (1) { - if (! valid_window(win, NULL, 0)) { - if (time(NULL) > start + waittime) { - break; - } - usleep(ms * 1000); - continue; - } - if (dpy && ! XGetWindowAttributes(dpy, win, &attr)) { - return 0; - } - if (attr.map_state == IsViewable) { - return 1; - } - usleep(ms * 1000); - } - return 0; -#endif /* NO_X11 */ -} - -/* - * initialize a fb for the X display - */ -XImage *initialize_xdisplay_fb(void) { -#if NO_X11 - if (raw_fb_str) { - return initialize_raw_fb(0); - } - return NULL; -#else - XImage *fb; - char *vis_str = visual_str; - int try = 0, subwin_tries = 3; - XErrorHandler old_handler = NULL; - int subwin_bs; - - if (raw_fb_str) { - return initialize_raw_fb(0); - } - - X_LOCK; - if (subwin) { - if (subwin_wait_mapped) { - wait_until_mapped(subwin); - } - if (!valid_window((Window) subwin, NULL, 0)) { - rfbLogEnable(1); - rfbLog("invalid sub-window: 0x%lx\n", subwin); - X_UNLOCK; - clean_up_exit(1); - } - } - - if (overlay) { - /* - * ideally we'd like to not have to cook up the - * visual variables but rather let it all come out - * of XReadScreen(), however there is no way to get - * a default visual out of it, so we pretend -visual - * TrueColor:NN was supplied with NN usually 24. - */ - char str[32]; - Window twin = subwin ? subwin : rootwin; - XImage *xi; - - xi = xreadscreen(dpy, twin, 0, 0, 8, 8, False); - sprintf(str, "TrueColor:%d", xi->depth); - if (xi->depth != 24 && ! quiet) { - rfbLog("warning: overlay image has depth %d " - "instead of 24.\n", xi->depth); - } - XDestroyImage(xi); - if (visual_str != NULL && ! quiet) { - rfbLog("warning: replacing '-visual %s' by '%s' " - "for use with -overlay\n", visual_str, str); - } - vis_str = strdup(str); - } - - if (xform24to32) { - if (DefaultDepth(dpy, scr) == 24) { - vis_str = strdup("TrueColor:32"); - rfbLog("initialize_xdisplay_fb: vis_str set to: %s\n", - vis_str); - visual_id = (VisualID) 0; - visual_depth = 0; - set_visual_str_to_something = 1; - } - } else if (DefaultDepth(dpy, scr) < 8) { - /* check very low bpp case, e.g. mono or vga16 */ - Screen *s = DefaultScreenOfDisplay(dpy); - XImage *xi = XGetImage_wr(dpy, DefaultRootWindow(dpy), 0, 0, 2, 2, AllPlanes, - ZPixmap); - if (xi && xi->bits_per_pixel < 8) { - int lowbpp = xi->bits_per_pixel; - if (!vis_str) { - char tmp[32]; - sprintf(tmp, "0x%x:8", (int) s->root_visual->visualid); - vis_str = strdup(tmp); - rfbLog("initialize_xdisplay_fb: low bpp[%d], vis_str " - "set to: %s\n", lowbpp, vis_str); - } - if (using_shm) { - using_shm = 0; - rfbLog("initialize_xdisplay_fb: low bpp[%d], " - "disabling shm\n", lowbpp); - } - visual_id = (VisualID) 0; - visual_depth = 0; - set_visual_str_to_something = 1; - } - if (xi) { - XDestroyImage(xi); - } - } - - if (vis_str != NULL) { - set_visual(vis_str); - if (vis_str != visual_str) { - free(vis_str); - } - } -if (0) fprintf(stderr, "vis_str %s\n", vis_str ? vis_str : "notset"); - - /* set up parameters for subwin or non-subwin cases: */ - - again: - - if (! subwin) { - /* full screen */ - window = rootwin; - dpy_x = wdpy_x = DisplayWidth(dpy, scr); - dpy_y = wdpy_y = DisplayHeight(dpy, scr); - off_x = 0; - off_y = 0; - /* this may be overridden via visual_id below */ - default_visual = DefaultVisual(dpy, scr); - } else { - /* single window */ - XWindowAttributes attr; - - window = (Window) subwin; - if (! XGetWindowAttributes(dpy, window, &attr)) { - rfbLogEnable(1); - rfbLog("invalid window: 0x%lx\n", window); - X_UNLOCK; - clean_up_exit(1); - } - dpy_x = wdpy_x = attr.width; - dpy_y = wdpy_y = attr.height; - - subwin_bs = attr.backing_store; - - /* this may be overridden via visual_id below */ - default_visual = attr.visual; - - X_UNLOCK; - set_offset(); - X_LOCK; - } - - initialize_clipshift(); - - /* initialize depth to reasonable value, visual_id may override */ - depth = DefaultDepth(dpy, scr); - -if (0) fprintf(stderr, "DefaultDepth: %d visial_id: %d\n", depth, (int) visual_id); - - if (visual_id) { - int n; - XVisualInfo vinfo_tmpl, *vinfo; - - /* - * we are in here from -visual or -overlay options - * visual_id and visual_depth were set in set_visual(). - */ - - vinfo_tmpl.visualid = visual_id; - vinfo = XGetVisualInfo(dpy, VisualIDMask, &vinfo_tmpl, &n); - if (vinfo == NULL || n == 0) { - rfbLogEnable(1); - rfbLog("could not match visual_id: 0x%x\n", - (int) visual_id); - X_UNLOCK; - clean_up_exit(1); - } - default_visual = vinfo->visual; - depth = vinfo->depth; - if (visual_depth) { - /* force it from -visual MooColor:NN */ - depth = visual_depth; - } - if (! quiet) { - fprintf(stderr, " initialize_xdisplay_fb()\n"); - fprintf(stderr, " Visual*: %p\n", - (void *) vinfo->visual); - fprintf(stderr, " visualid: 0x%x\n", - (int) vinfo->visualid); - fprintf(stderr, " screen: %d\n", vinfo->screen); - fprintf(stderr, " depth: %d\n", vinfo->depth); - fprintf(stderr, " class: %d\n", vinfo->class); - fprintf(stderr, " red_mask: 0x%08lx %s\n", - vinfo->red_mask, bitprint(vinfo->red_mask, 32)); - fprintf(stderr, " green_mask: 0x%08lx %s\n", - vinfo->green_mask, bitprint(vinfo->green_mask, 32)); - fprintf(stderr, " blue_mask: 0x%08lx %s\n", - vinfo->blue_mask, bitprint(vinfo->blue_mask, 32)); - fprintf(stderr, " cmap_size: %d\n", - vinfo->colormap_size); - fprintf(stderr, " bits b/rgb: %d\n", - vinfo->bits_per_rgb); - fprintf(stderr, "\n"); - } - XFree_wr(vinfo); - } - - if (! quiet) { - rfbLog("Default visual ID: 0x%x\n", - (int) XVisualIDFromVisual(default_visual)); - } - - if (subwin) { - int shift = 0, resize = 0; - int subwin_x, subwin_y; - int disp_x = DisplayWidth(dpy, scr); - int disp_y = DisplayHeight(dpy, scr); - Window twin; - /* subwins can be a dicey if they are changing size... */ - trapped_xerror = 0; - old_handler = XSetErrorHandler(trap_xerror); /* reset in if(subwin) block below */ - XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x, - &subwin_y, &twin); - - if (wdpy_x > disp_x) { - resize = 1; - dpy_x = wdpy_x = disp_x - 4; - } - if (wdpy_y > disp_y) { - resize = 1; - dpy_y = wdpy_y = disp_y - 4; - } - - if (subwin_x + wdpy_x > disp_x) { - shift = 1; - subwin_x = disp_x - wdpy_x - 3; - } - if (subwin_y + wdpy_y > disp_y) { - shift = 1; - subwin_y = disp_y - wdpy_y - 3; - } - if (subwin_x < 0) { - shift = 1; - subwin_x = 1; - } - if (subwin_y < 0) { - shift = 1; - subwin_y = 1; - } - - if (resize) { - XResizeWindow(dpy, window, wdpy_x, wdpy_y); - } - if (shift) { - XMoveWindow(dpy, window, subwin_x, subwin_y); - off_x = subwin_x; - off_y = subwin_y; - } - XMapRaised(dpy, window); - XRaiseWindow(dpy, window); - XSync(dpy, False); - } - try++; - - if (nofb) { - /* - * For -nofb we do not allocate the framebuffer, so we - * can save a few MB of memory. - */ - fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap, - 0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0); - - } else if (visual_id) { - /* - * we need to call XCreateImage to supply the visual - */ - fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap, - 0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0); - if (fb) { - fb->data = (char *) malloc(fb->bytes_per_line * fb->height); - } - - } else { - fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, - ZPixmap); - if (! quiet) { - rfbLog("Read initial data from X display into" - " framebuffer.\n"); - } - } - - if (subwin) { - XSetErrorHandler(old_handler); - if (trapped_xerror || fb == NULL) { - rfbLog("trapped GetImage at SUBWIN creation.\n"); - if (try < subwin_tries) { - usleep(250 * 1000); - if (!get_window_size(window, &wdpy_x, &wdpy_y)) { - rfbLogEnable(1); - rfbLog("could not get size of subwin " - "0x%lx\n", subwin); - X_UNLOCK; - clean_up_exit(1); - } - goto again; - } - } - trapped_xerror = 0; - - } else if (fb == NULL) { - XEvent xev; - rfbLog("initialize_xdisplay_fb: *** fb creation failed: 0x%x try: %d\n", fb, try); -#if LIBVNCSERVER_HAVE_LIBXRANDR - if (xrandr_present && xrandr_base_event_type) { - int cnt = 0; - while (XCheckTypedEvent(dpy, xrandr_base_event_type + RRScreenChangeNotify, &xev)) { - XRRScreenChangeNotifyEvent *rev; - rev = (XRRScreenChangeNotifyEvent *) &xev; - - rfbLog("initialize_xdisplay_fb: XRANDR event while redoing fb[%d]:\n", cnt++); - rfbLog(" serial: %d\n", (int) rev->serial); - rfbLog(" timestamp: %d\n", (int) rev->timestamp); - rfbLog(" cfg_timestamp: %d\n", (int) rev->config_timestamp); - rfbLog(" size_id: %d\n", (int) rev->size_index); - rfbLog(" sub_pixel: %d\n", (int) rev->subpixel_order); - rfbLog(" rotation: %d\n", (int) rev->rotation); - rfbLog(" width: %d\n", (int) rev->width); - rfbLog(" height: %d\n", (int) rev->height); - rfbLog(" mwidth: %d mm\n", (int) rev->mwidth); - rfbLog(" mheight: %d mm\n", (int) rev->mheight); - rfbLog("\n"); - rfbLog("previous WxH: %dx%d\n", wdpy_x, wdpy_y); - - xrandr_width = rev->width; - xrandr_height = rev->height; - xrandr_timestamp = rev->timestamp; - xrandr_cfg_time = rev->config_timestamp; - xrandr_rotation = (int) rev->rotation; - - rfbLog("initialize_xdisplay_fb: updating XRANDR config...\n"); - XRRUpdateConfiguration(&xev); - } - } -#endif - if (try < 5) { - XFlush_wr(dpy); - usleep(250 * 1000); - if (try < 3) { - XSync(dpy, False); - } else if (try >= 3) { - XSync(dpy, True); - } - goto again; - } - } - if (use_snapfb) { - initialize_snap_fb(); - } - - X_UNLOCK; - - if (fb->bits_per_pixel == 24 && ! quiet) { - rfbLog("warning: 24 bpp may have poor performance.\n"); - } - return fb; -#endif /* NO_X11 */ -} - -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) { - - int m, n; - char *p, *tstr; - double f, f2; - - *factor_x = 1.0; - *factor_y = 1.0; - *scaling = 0; - *blend = 1; - *nomult4 = 0; - *pad = 0; - *interpolate = 0; - *numer = 0, *denom = 0; - - if (str == NULL || str[0] == '\0') { - return; - } - tstr = strdup(str); - - if ( (p = strchr(tstr, ':')) != NULL) { - /* options */ - if (strstr(p+1, "nb") != NULL) { - *blend = 0; - } - if (strstr(p+1, "fb") != NULL) { - *blend = 2; - } - if (strstr(p+1, "n4") != NULL) { - *nomult4 = 1; - } - if (strstr(p+1, "in") != NULL) { - *interpolate = 1; - } - if (strstr(p+1, "pad") != NULL) { - *pad = 1; - } - if (strstr(p+1, "nocr") != NULL) { - /* global */ - scaling_copyrect = 0; - } else if (strstr(p+1, "cr") != NULL) { - /* global */ - scaling_copyrect = 1; - } - *p = '\0'; - } - - if (strchr(tstr, '.') != NULL) { - double test, diff, eps = 1.0e-7; - if (sscanf(tstr, "%lfx%lf", &f, &f2) == 2) { - *factor_x = (double) f; - *factor_y = (double) f2; - } else if (sscanf(tstr, "%lf", &f) != 1) { - rfbLogEnable(1); - rfbLog("invalid -scale arg: %s\n", tstr); - clean_up_exit(1); - } else { - *factor_x = (double) f; - *factor_y = (double) f; - } - /* look for common fractions from small ints: */ - if (*factor_x == *factor_y) { - for (n=2; n<=10; n++) { - for (m=1; m<n; m++) { - test = ((double) m)/ n; - diff = *factor_x - test; - if (-eps < diff && diff < eps) { - *numer = m; - *denom = n; - break; - - } - } - if (*denom) { - break; - } - } - if (*factor_x < 0.01) { - rfbLogEnable(1); - rfbLog("-scale factor too small: %f\n", *factor_x); - clean_up_exit(1); - } - } - } else if (sscanf(tstr, "%dx%d", &m, &n) == 2 && w_in > 0 && h_in > 0) { - *factor_x = ((double) m) / ((double) w_in); - *factor_y = ((double) n) / ((double) h_in); - } else { - if (sscanf(tstr, "%d/%d", &m, &n) != 2) { - if (sscanf(tstr, "%d", &m) != 1) { - rfbLogEnable(1); - rfbLog("invalid -scale arg: %s\n", tstr); - clean_up_exit(1); - } else { - /* e.g. -scale 1 or -scale 2 */ - n = 1; - } - } - if (n <= 0 || m <=0) { - rfbLogEnable(1); - rfbLog("invalid -scale arg: %s\n", tstr); - clean_up_exit(1); - } - *factor_x = ((double) m)/ n; - *factor_y = ((double) m)/ n; - if (*factor_x < 0.01) { - rfbLogEnable(1); - rfbLog("-scale factor too small: %f\n", *factor_x); - clean_up_exit(1); - } - *numer = m; - *denom = n; - } - if (*factor_x == 1.0 && *factor_y == 1.0) { - if (! quiet) { - rfbLog("scaling disabled for factor %f %f\n", *factor_x, *factor_y); - } - } else { - *scaling = 1; - } - free(tstr); -} - -int parse_rotate_string(char *str, int *mode) { - int m = ROTATE_NONE; - if (str == NULL || !strcmp(str, "") || !strcmp(str, "0")) { - m = ROTATE_NONE; - } else if (!strcmp(str, "x")) { - m = ROTATE_X; - } else if (!strcmp(str, "y")) { - m = ROTATE_Y; - } else if (!strcmp(str, "xy") || !strcmp(str, "yx") || - !strcmp(str,"+180") || !strcmp(str,"-180") || !strcmp(str,"180")) { - m = ROTATE_XY; - } else if (!strcmp(str, "+90") || !strcmp(str, "90")) { - m = ROTATE_90; - } else if (!strcmp(str, "+90x") || !strcmp(str, "90x")) { - m = ROTATE_90X; - } else if (!strcmp(str, "+90y") || !strcmp(str, "90y")) { - m = ROTATE_90Y; - } else if (!strcmp(str, "-90") || !strcmp(str, "270") || - !strcmp(str, "+270")) { - m = ROTATE_270; - } else { - rfbLog("invalid -rotate mode: %s\n", str); - } - if (mode) { - *mode = m; - } - return m; -} - -int scale_round(int len, double fac) { - double eps = 0.000001; - - len = (int) (len * fac + eps); - if (len < 1) { - len = 1; - } - return len; -} - -static void setup_scaling(int *width_in, int *height_in) { - int width = *width_in; - int height = *height_in; - - parse_scale_string(scale_str, &scale_fac_x, &scale_fac_y, &scaling, &scaling_blend, - &scaling_nomult4, &scaling_pad, &scaling_interpolate, - &scale_numer, &scale_denom, *width_in, *height_in); - - if (scaling) { - width = scale_round(width, scale_fac_x); - height = scale_round(height, scale_fac_y); - if (scale_denom && scaling_pad) { - /* it is not clear this padding is useful anymore */ - rfbLog("width %% denom: %d %% %d = %d\n", width, - scale_denom, width % scale_denom); - rfbLog("height %% denom: %d %% %d = %d\n", height, - scale_denom, height % scale_denom); - if (width % scale_denom != 0) { - int w = width; - w += scale_denom - (w % scale_denom); - if (!scaling_nomult4 && w % 4 != 0) { - /* need to make mult of 4 as well */ - int c = 0; - while (w % 4 != 0 && c++ <= 5) { - w += scale_denom; - } - } - width = w; - rfbLog("padded width to: %d (mult of %d%s\n", - width, scale_denom, !scaling_nomult4 ? - " and 4)" : ")"); - } - if (height % scale_denom != 0) { - height += scale_denom - (height % scale_denom); - rfbLog("padded height to: %d (mult of %d)\n", - height, scale_denom); - } - } - if (!scaling_nomult4 && width % 4 != 0 && width > 2) { - /* reset width to be multiple of 4 */ - int width0 = width; - if ((width+1) % 4 == 0) { - width = width+1; - } else if ((width-1) % 4 == 0) { - width = width-1; - } else if ((width+2) % 4 == 0) { - width = width+2; - } - rfbLog("reset scaled width %d -> %d to be a multiple of" - " 4 (to\n", width0, width); - rfbLog("make vncviewers happy). use -scale m/n:n4 to " - "disable.\n"); - } - scaled_x = width; - scaled_y = height; - - *width_in = width; - *height_in = height; - } -} - -static void setup_rotating(void) { - char *rs = rotating_str; - - rotating_cursors = 1; - if (rs && strstr(rs, "nc:") == rs) { - rs += strlen("nc:"); - rotating_cursors = 0; - } - - rotating = parse_rotate_string(rs, NULL); - if (! rotating) { - rotating_cursors = 0; - } - - if (rotating == ROTATE_90 || rotating == ROTATE_90X || - rotating == ROTATE_90Y || rotating == ROTATE_270) { - rotating_same = 0; - } else { - rotating_same = 1; - } -} - -static rfbBool set_xlate_wrapper(rfbClientPtr cl) { - static int first = 1; - if (first) { - first = 0; - } else if (ncache) { - int save = ncache_xrootpmap; - rfbLog("set_xlate_wrapper: clearing -ncache for new pixel format.\n"); - INPUT_LOCK; - ncache_xrootpmap = 0; - check_ncache(1, 0); - ncache_xrootpmap = save; - INPUT_UNLOCK; - } - return rfbSetTranslateFunction(cl); -} - -/* - * initialize the rfb framebuffer/screen - */ -void initialize_screen(int *argc, char **argv, XImage *fb) { - int have_masks = 0; - int width = fb->width; - int height = fb->height; - int create_screen = screen ? 0 : 1; - int bits_per_color; - int fb_bpp, fb_Bpl, fb_depth; - int locked_sends = 0; - - bpp = fb->bits_per_pixel; - - fb_bpp = (int) fb->bits_per_pixel; - fb_Bpl = (int) fb->bytes_per_line; - fb_depth = (int) fb->depth; - - rfbLog("initialize_screen: fb_depth/fb_bpp/fb_Bpl %d/%d/%d\n", fb_depth, - fb_bpp, fb_Bpl); - - main_bytes_per_line = fb->bytes_per_line; - - if (cmap8to24) { - if (raw_fb) { - if (!quiet) rfbLog("disabling -8to24 mode" - " in raw_fb mode.\n"); - cmap8to24 = 0; - } else if (depth == 24) { - if (fb_bpp != 32) { - if (!quiet) rfbLog("disabling -8to24 mode:" - " bpp != 32 with depth == 24\n"); - cmap8to24 = 0; - } - } else if (depth <= 16) { - /* need to cook up the screen fb to be depth 24 */ - fb_bpp = 32; - fb_depth = 24; - } else { - if (!quiet) rfbLog("disabling -8to24 mode:" - " default depth not 16 or less\n"); - cmap8to24 = 0; - } - } - - setup_scaling(&width, &height); - - if (scaling) { - rfbLog("scaling screen: %dx%d -> %dx%d\n", fb->width, fb->height, scaled_x, scaled_y); - rfbLog("scaling screen: scale_fac_x=%.5f scale_fac_y=%.5f\n", scale_fac_x, scale_fac_y); - - rfb_bytes_per_line = (main_bytes_per_line / fb->width) * width; - } else { - rfb_bytes_per_line = main_bytes_per_line; - } - - setup_rotating(); - - if (rotating) { - if (! rotating_same) { - int t, b = main_bytes_per_line / fb->width; - if (scaling) { - rot_bytes_per_line = b * height; - } else { - rot_bytes_per_line = b * fb->height; - } - t = width; - width = height; /* The big swap... */ - height = t; - } else { - rot_bytes_per_line = rfb_bytes_per_line; - } - } - -#ifndef NO_NCACHE - if (ncache > 0 && !nofb) { -# ifdef MACOSX - if (! raw_fb_str || macosx_console) { -# else - if (! raw_fb_str) { -# endif - - char *new_fb; - int sz = fb->height * fb->bytes_per_line; - int ns = 1+ncache; - - if (ncache_xrootpmap) { - ns++; - } - - new_fb = (char *) calloc((size_t) (sz * ns), 1); - if (fb->data) { - memcpy(new_fb, fb->data, sz); - free(fb->data); - } - fb->data = new_fb; - fb->height *= (ns); - height *= (ns); - ncache0 = ncache; - } - } -#endif - - if (cmap8to24) { - if (depth <= 8) { - rfb_bytes_per_line *= 4; - rot_bytes_per_line *= 4; - } else if (depth <= 16) { - rfb_bytes_per_line *= 2; - rot_bytes_per_line *= 2; - } - } - - /* - * These are just hints wrt pixel format just to let - * rfbGetScreen/rfbNewFramebuffer proceed with reasonable - * defaults. We manually set them in painful detail below. - */ - bits_per_color = guess_bits_per_color(fb_bpp); - - if (lock_client_sends(-1) == 0) { - lock_client_sends(1); - locked_sends = 1; - } - - /* n.b. samplesPerPixel (set = 1 here) seems to be unused. */ - if (create_screen) { - if (use_stunnel) { - setup_stunnel(0, argc, argv); - } - if (use_openssl) { - if (use_stunnel && enc_str && !strcmp(enc_str, "none")) { - /* emulating HTTPS oneport */ - ; - } else { - openssl_init(0); - } - } - screen = rfbGetScreen(argc, argv, width, height, - bits_per_color, 1, fb_bpp/8); - if (screen && http_dir) { - http_connections(1); - } - if (unix_sock) { - unix_sock_fd = listen_unix(unix_sock); - } - } else { - /* set set frameBuffer member below. */ - rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n", - screen, NULL, width, height, bits_per_color, 1, fb_bpp/8); - - /* these are probably overwritten, but just to be safe: */ - screen->bitsPerPixel = fb_bpp; - screen->depth = fb_depth; - - rfb_new_framebuffer(screen, NULL, width, height, - bits_per_color, 1, (int) fb_bpp/8); - } - if (! screen) { - int i; - rfbLogEnable(1); - rfbLog("\n"); - rfbLog("failed to create rfb screen.\n"); - for (i=0; i< *argc; i++) { - rfbLog("\t[%d] %s\n", i, argv[i]); - } - clean_up_exit(1); - } - - if (create_screen && *argc != 1) { - int i; - rfbLogEnable(1); - rfbLog("*** unrecognized option(s) ***\n"); - for (i=1; i< *argc; i++) { - rfbLog("\t[%d] %s\n", i, argv[i]); - } - rfbLog("For a list of options run: x11vnc -opts\n"); - rfbLog("or for the full help: x11vnc -help\n"); - rfbLog("\n"); - rfbLog("Here is a list of removed or obsolete" - " options:\n"); - rfbLog("\n"); - rfbLog("removed: -hints, -nohints\n"); - rfbLog("removed: -cursorposall\n"); - rfbLog("removed: -nofilexfer, now the default.\n"); - rfbLog("\n"); - rfbLog("renamed: -old_copytile, use -onetile\n"); - rfbLog("renamed: -mouse, use -cursor\n"); - rfbLog("renamed: -mouseX, use -cursor X\n"); - rfbLog("renamed: -X, use -cursor X\n"); - rfbLog("renamed: -nomouse, use -nocursor\n"); - rfbLog("renamed: -old_pointer, use -pointer_mode 1\n"); - - clean_up_exit(1); - } - - /* set up format from scratch: */ - if (rotating && ! rotating_same) { - screen->paddedWidthInBytes = rot_bytes_per_line; - } else { - screen->paddedWidthInBytes = rfb_bytes_per_line; - } - screen->serverFormat.bitsPerPixel = fb_bpp; - screen->serverFormat.depth = fb_depth; - screen->serverFormat.trueColour = TRUE; - - screen->serverFormat.redShift = 0; - screen->serverFormat.greenShift = 0; - screen->serverFormat.blueShift = 0; - screen->serverFormat.redMax = 0; - screen->serverFormat.greenMax = 0; - screen->serverFormat.blueMax = 0; - - /* these main_* formats are used generally. */ - main_red_shift = 0; - main_green_shift = 0; - main_blue_shift = 0; - main_red_max = 0; - main_green_max = 0; - main_blue_max = 0; - main_red_mask = fb->red_mask; - main_green_mask = fb->green_mask; - main_blue_mask = fb->blue_mask; - - have_masks = ((fb->red_mask|fb->green_mask|fb->blue_mask) != 0); - if (force_indexed_color) { - have_masks = 0; - } - - if (cmap8to24 && depth <= 16 && dpy) { - XVisualInfo vinfo; - vinfo.red_mask = 0; - vinfo.green_mask = 0; - vinfo.blue_mask = 0; - /* more cooking up... */ - have_masks = 2; - /* need to fetch TrueColor visual */ - X_LOCK; - if (dpy -#if !NO_X11 - && XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinfo) -#endif - ) { - main_red_mask = vinfo.red_mask; - main_green_mask = vinfo.green_mask; - main_blue_mask = vinfo.blue_mask; - } else if (fb->byte_order == LSBFirst) { - main_red_mask = 0x00ff0000; - main_green_mask = 0x0000ff00; - main_blue_mask = 0x000000ff; - } else { - main_red_mask = 0x000000ff; - main_green_mask = 0x0000ff00; - main_blue_mask = 0x00ff0000; - } - X_UNLOCK; - } - - if (raw_fb_str && raw_fb_pixfmt) { - char *fmt = strdup(raw_fb_pixfmt); - uppercase(fmt); - if (strstr(fmt, "GREY")) { - set_greyscale_colormap(); - } else if (strstr(fmt, "HI240")) { - set_hi240_colormap(); - } else { - unset_colormap(); - } - free(fmt); - } - - if (! have_masks && screen->serverFormat.bitsPerPixel <= 16 - && dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) { - /* indexed color. we let 1 <= bpp <= 16, but it is normally 8 */ - if (!quiet) { - rfbLog("\n"); - rfbLog("X display %s is %dbpp indexed color, depth=%d\n", - DisplayString(dpy), screen->serverFormat.bitsPerPixel, - screen->serverFormat.depth); - if (! flash_cmap && ! overlay) { - rfbLog("\n"); - rfbLog("In 8bpp PseudoColor mode if you " - "experience color\n"); - rfbLog("problems you may want to enable " - "following the\n"); - rfbLog("changing colormap by using the " - "-flashcmap option.\n"); - rfbLog("\n"); - } - } - if (screen->serverFormat.depth < 8) { - rfbLog("resetting serverFormat.depth %d -> 8.\n", - screen->serverFormat.depth); - rfbLog("resetting serverFormat.bpp %d -> 8.\n", - screen->serverFormat.bitsPerPixel); - screen->serverFormat.depth = 8; - screen->serverFormat.bitsPerPixel = 8; - } - if (screen->serverFormat.depth > 8) { - rfbLog("WARNING: indexed color depth > 8, Tight encoding will crash.\n"); - } - - screen->serverFormat.trueColour = FALSE; - indexed_color = 1; - set_colormap(1); - debug_colormap(fb); - } else { - /* - * general case, we call it truecolor, but could be direct - * color, static color, etc.... - */ - if (! quiet) { - if (raw_fb) { - rfbLog("\n"); - rfbLog("Raw fb at addr %p is %dbpp depth=%d " - "true color\n", raw_fb_addr, - fb_bpp, fb_depth); - } else if (! dpy) { - ; - } else if (have_masks == 2) { - rfbLog("\n"); - rfbLog("X display %s is %dbpp depth=%d indexed " - "color (-8to24 mode)\n", DisplayString(dpy), - fb->bits_per_pixel, fb->depth); - } else { - rfbLog("\n"); - rfbLog("X display %s is %dbpp depth=%d true " - "color\n", DisplayString(dpy), - fb_bpp, fb_depth); - } - } - - indexed_color = 0; - - if (!have_masks) { - int M, B = bits_per_color; - - if (3*B > fb_bpp) B--; - if (B < 1) B = 1; - M = (1 << B) - 1; - - rfbLog("WARNING: all TrueColor RGB masks are zero!\n"); - rfbLog("WARNING: cooking something up for VNC fb... B=%d M=%d\n", B, M); - main_red_mask = M; - main_green_mask = M; - main_blue_mask = M; - main_red_mask = main_red_mask << (2*B); - main_green_mask = main_green_mask << (1*B); - main_blue_mask = main_blue_mask << (0*B); - fprintf(stderr, " red_mask: 0x%08lx %s\n", main_red_mask, - bitprint(main_red_mask, 32)); - fprintf(stderr, " green_mask: 0x%08lx %s\n", main_green_mask, - bitprint(main_green_mask, 32)); - fprintf(stderr, " blue_mask: 0x%08lx %s\n", main_blue_mask, - bitprint(main_blue_mask, 32)); - } - - /* convert masks to bit shifts and max # colors */ - if (main_red_mask) { - while (! (main_red_mask - & (1 << screen->serverFormat.redShift))) { - screen->serverFormat.redShift++; - } - } - if (main_green_mask) { - while (! (main_green_mask - & (1 << screen->serverFormat.greenShift))) { - screen->serverFormat.greenShift++; - } - } - if (main_blue_mask) { - while (! (main_blue_mask - & (1 << screen->serverFormat.blueShift))) { - screen->serverFormat.blueShift++; - } - } - screen->serverFormat.redMax - = main_red_mask >> screen->serverFormat.redShift; - screen->serverFormat.greenMax - = main_green_mask >> screen->serverFormat.greenShift; - screen->serverFormat.blueMax - = main_blue_mask >> screen->serverFormat.blueShift; - - main_red_max = screen->serverFormat.redMax; - main_green_max = screen->serverFormat.greenMax; - main_blue_max = screen->serverFormat.blueMax; - - main_red_shift = screen->serverFormat.redShift; - main_green_shift = screen->serverFormat.greenShift; - main_blue_shift = screen->serverFormat.blueShift; - } - -#if !SMALL_FOOTPRINT - if (verbose) { - fprintf(stderr, "\n"); - fprintf(stderr, "FrameBuffer Info:\n"); - fprintf(stderr, " width: %d\n", fb->width); - fprintf(stderr, " height: %d\n", fb->height); - fprintf(stderr, " scaled_width: %d\n", width); - fprintf(stderr, " scaled_height: %d\n", height); - fprintf(stderr, " indexed_color: %d\n", indexed_color); - fprintf(stderr, " bits_per_pixel: %d\n", fb->bits_per_pixel); - fprintf(stderr, " depth: %d\n", fb->depth); - fprintf(stderr, " red_mask: 0x%08lx %s\n", fb->red_mask, - bitprint(fb->red_mask, 32)); - fprintf(stderr, " green_mask: 0x%08lx %s\n", fb->green_mask, - bitprint(fb->green_mask, 32)); - fprintf(stderr, " blue_mask: 0x%08lx %s\n", fb->blue_mask, - bitprint(fb->blue_mask, 32)); - if (cmap8to24) { - fprintf(stderr, " 8to24 info:\n"); - fprintf(stderr, " fb_bpp: %d\n", fb_bpp); - fprintf(stderr, " fb_depth: %d\n", fb_depth); - fprintf(stderr, " red_mask: 0x%08lx %s\n", main_red_mask, - bitprint(main_red_mask, 32)); - fprintf(stderr, " green_mask: 0x%08lx %s\n", main_green_mask, - bitprint(main_green_mask, 32)); - fprintf(stderr, " blue_mask: 0x%08lx %s\n", main_blue_mask, - bitprint(main_blue_mask, 32)); - } - fprintf(stderr, " red: max: %3d shift: %2d\n", - main_red_max, main_red_shift); - fprintf(stderr, " green: max: %3d shift: %2d\n", - main_green_max, main_green_shift); - fprintf(stderr, " blue: max: %3d shift: %2d\n", - main_blue_max, main_blue_shift); - fprintf(stderr, " mainfb_bytes_per_line: %d\n", - main_bytes_per_line); - fprintf(stderr, " rfb_fb_bytes_per_line: %d\n", - rfb_bytes_per_line); - fprintf(stderr, " rot_fb_bytes_per_line: %d\n", - rot_bytes_per_line); - fprintf(stderr, " raw_fb_bytes_per_line: %d\n", - raw_fb_bytes_per_line); - switch(fb->format) { - case XYBitmap: - fprintf(stderr, " format: XYBitmap\n"); break; - case XYPixmap: - fprintf(stderr, " format: XYPixmap\n"); break; - case ZPixmap: - fprintf(stderr, " format: ZPixmap\n"); break; - default: - fprintf(stderr, " format: %d\n", fb->format); break; - } - switch(fb->byte_order) { - case LSBFirst: - fprintf(stderr, " byte_order: LSBFirst\n"); break; - case MSBFirst: - fprintf(stderr, " byte_order: MSBFirst\n"); break; - default: - fprintf(stderr, " byte_order: %d\n", fb->byte_order); - break; - } - fprintf(stderr, " bitmap_pad: %d\n", fb->bitmap_pad); - fprintf(stderr, " bitmap_unit: %d\n", fb->bitmap_unit); - switch(fb->bitmap_bit_order) { - case LSBFirst: - fprintf(stderr, " bitmap_bit_order: LSBFirst\n"); break; - case MSBFirst: - fprintf(stderr, " bitmap_bit_order: MSBFirst\n"); break; - default: - fprintf(stderr, " bitmap_bit_order: %d\n", - fb->bitmap_bit_order); break; - } - } - if (overlay && ! quiet) { - rfbLog("\n"); - rfbLog("Overlay mode enabled: If you experience color\n"); - rfbLog("problems when popup menus are on the screen, try\n"); - rfbLog("disabling SaveUnders in your X server, one way is\n"); - rfbLog("to start the X server with the '-su' option, e.g.:\n"); - rfbLog("Xsun -su ... see Xserver(1), xinit(1) for more info.\n"); - rfbLog("\n"); - } -#endif - /* nofb is for pointer/keyboard only handling. */ - if (nofb) { - main_fb = NULL; - rfb_fb = main_fb; - cmap8to24_fb = NULL; - rot_fb = NULL; - screen->displayHook = nofb_hook; - } else { - main_fb = fb->data; - rfb_fb = NULL; - cmap8to24_fb = NULL; - rot_fb = NULL; - - if (cmap8to24) { - int n = main_bytes_per_line * fb->height; - if (depth <= 8) { - n *= 4; - } else if (depth <= 16) { - n *= 2; - } - cmap8to24_fb = (char *) malloc(n); - memset(cmap8to24_fb, 0, n); - } - - if (rotating) { - int n = rot_bytes_per_line * height; - rot_fb = (char *) malloc(n); - memset(rot_fb, 0, n); - } - - if (scaling) { - int n = rfb_bytes_per_line * height; - - if (rotating && ! rotating_same) { - n = rot_bytes_per_line * height; - } - - rfb_fb = (char *) malloc(n); - memset(rfb_fb, 0, n); - - } else if (cmap8to24) { - rfb_fb = cmap8to24_fb; - } else { - rfb_fb = main_fb; - } - } - if (rot_fb) { - screen->frameBuffer = rot_fb; - } else { - screen->frameBuffer = rfb_fb; - } - if (verbose) { - fprintf(stderr, " rfb_fb: %p\n", rfb_fb); - fprintf(stderr, " main_fb: %p\n", main_fb); - fprintf(stderr, " 8to24_fb: %p\n", cmap8to24_fb); - fprintf(stderr, " rot_fb: %p\n", rot_fb); - fprintf(stderr, " snap_fb: %p\n", snap_fb); - fprintf(stderr, " raw_fb: %p\n", raw_fb); - fprintf(stderr, " fake_fb: %p\n", fake_fb); - fprintf(stderr, "\n"); - } - - /* may need, bpp, main_red_max, etc. */ - parse_wireframe(); - parse_scroll_copyrect(); - setup_cursors_and_push(); - - if (scaling || rotating || cmap8to24) { - mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0); - } - - if (! create_screen) { - rfbClientIteratorPtr iter; - rfbClientPtr cl; - - /* - * since bits_per_color above may have been approximate, - * try to reset the individual translation tables... - * we do not seem to need this with rfbGetScreen()... - */ - if (!quiet) rfbLog("calling setTranslateFunction()...\n"); - iter = rfbGetClientIterator(screen); - while ((cl = rfbClientIteratorNext(iter)) != NULL) { - screen->setTranslateFunction(cl); - } - rfbReleaseClientIterator(iter); - if (!quiet) rfbLog(" done.\n"); - - /* done for framebuffer change case */ - if (locked_sends) { - lock_client_sends(0); - } - - do_copy_screen = 1; - return; - } - - /* - * the rest is screen server initialization, etc, only needed - * at screen creation time. - */ - - /* event callbacks: */ - screen->newClientHook = new_client; - screen->kbdAddEvent = keyboard; - screen->ptrAddEvent = pointer_event; - screen->setXCutText = xcut_receive; - screen->setTranslateFunction = set_xlate_wrapper; - - screen->kbdReleaseAllKeys = kbd_release_all_keys; - screen->setSingleWindow = set_single_window; - screen->setServerInput = set_server_input; - screen->setTextChat = set_text_chat; - screen->getFileTransferPermission = get_file_transfer_permitted; - - /* called from inetd, we need to treat stdio as our socket */ - if (inetd && use_openssl) { - /* accept_openssl() called later */ - screen->port = 0; - } else if (inetd) { - int fd = dup(0); - if (fd < 0) { - rfbLogEnable(1); - rfbErr("dup(0) = %d failed.\n", fd); - rfbLogPerror("dup"); - clean_up_exit(1); - } - fclose(stdin); - fclose(stdout); - /* we keep stderr for logging */ - screen->inetdSock = fd; - screen->port = 0; - - } else if (! got_rfbport && auto_port > 0) { - int lport = find_free_port(auto_port, auto_port+200); - screen->autoPort = FALSE; - screen->port = lport; - } else if (! got_rfbport) { - screen->autoPort = TRUE; - } else if (got_rfbport && got_rfbport_val == 0) { - screen->autoPort = FALSE; - screen->port = 0; - } - - if (! got_nevershared && ! got_alwaysshared) { - if (shared) { - screen->alwaysShared = TRUE; - } else { - screen->neverShared = TRUE; - } - screen->dontDisconnect = TRUE; - } - if (! got_deferupdate) { - screen->deferUpdateTime = defer_update; - } else { - defer_update = screen->deferUpdateTime; - } - - if (noipv4 || getenv("IPV4_FAILS")) { - rfbBool ap = screen->autoPort; - int port = screen->port; - - if (getenv("IPV4_FAILS")) { - rfbLog("TESTING: IPV4_FAILS for rfbInitServer()\n"); - } - - screen->autoPort = FALSE; - screen->port = 0; - - rfbInitServer(screen); - - screen->autoPort = ap; - screen->port = port; - - } else { - rfbInitServer(screen); - } - - if (use_openssl) { - openssl_port(0); - if (https_port_num >= 0) { - https_port(0); - } - } else { - if (ipv6_listen) { - int fd = -1; - if (screen->port <= 0) { - if (got_rfbport) { - screen->port = got_rfbport_val; - } else { - int ap = 5900; - if (auto_port > 0) { - ap = auto_port; - } - screen->port = find_free_port6(ap, ap+200); - } - } - fd = listen6(screen->port); - if (fd < 0) { - ipv6_listen = 0; - rfbLog("Not listening on IPv6 interface.\n"); - } else { - rfbLog("Listening %s on IPv6 port %d (socket %d)\n", - screen->listenSock < 0 ? "only" : "also", - screen->port, fd); - ipv6_listen_fd = fd; - } - } - } - - install_passwds(); - - if (locked_sends) { - lock_client_sends(0); - } - return; -} - -#define DO_AVAHI \ - if (avahi) { \ - avahi_initialise(); \ - avahi_advertise(vnc_desktop_name, host, lport); \ - usleep(1000*1000); \ - } - -void announce(int lport, int ssl, char *iface) { - - char *host = this_host(); - char *tvdt; - - if (remote_direct) { - return; - } - - if (! ssl) { - tvdt = "The VNC desktop is: "; - } else { - if (enc_str && !strcmp(enc_str, "none")) { - tvdt = "The VNC desktop is: "; - } else if (enc_str) { - tvdt = "The ENC VNC desktop is: "; - } else { - tvdt = "The SSL VNC desktop is: "; - } - } - - if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) { - host = iface; - } - if (host != NULL) { - /* note that vncviewer special cases 5900-5999 */ - int sz = 256; - if (inetd) { - ; /* should not occur (port) */ - } else if (quiet) { - if (lport >= 5900) { - snprintf(vnc_desktop_name, sz, "%s:%d", - host, lport - 5900); - DO_AVAHI - fprintf(stderr, "\n%s %s\n", tvdt, - vnc_desktop_name); - } else { - snprintf(vnc_desktop_name, sz, "%s:%d", - host, lport); - DO_AVAHI - fprintf(stderr, "\n%s %s\n", tvdt, - vnc_desktop_name); - } - } else if (lport >= 5900) { - snprintf(vnc_desktop_name, sz, "%s:%d", - host, lport - 5900); - DO_AVAHI - fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name); - if (lport >= 6000) { - rfbLog("possible aliases: %s:%d, " - "%s::%d\n", host, lport, - host, lport); - } - } else { - snprintf(vnc_desktop_name, sz, "%s:%d", - host, lport); - DO_AVAHI - fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name); - rfbLog("possible alias: %s::%d\n", - host, lport); - } - } -} - -static void announce_http(int lport, int ssl, char *iface, char *extra) { - - char *host = this_host(); - char *jvu; - int http = 0; - - if (enc_str && !strcmp(enc_str, "none") && !use_stunnel) { - jvu = "Java viewer URL: http"; - http = 1; - } else if (ssl == 1) { - jvu = "Java SSL viewer URL: https"; - } else if (ssl == 2) { - jvu = "Java SSL viewer URL: http"; - http = 1; - } else { - jvu = "Java viewer URL: http"; - http = 1; - } - - if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) { - host = iface; - } - if (http && getenv("X11VNC_HTTP_LISTEN_LOCALHOST")) { - host = "localhost"; - } - if (host != NULL) { - if (! inetd) { - fprintf(stderr, "%s://%s:%d/%s\n", jvu, host, lport, extra); - } - } -} - -void do_announce_http(void) { - if (!screen) { - return; - } - if (remote_direct) { - return; - } - - /* XXX ipv6? */ - if ((screen->httpListenSock > -1 || ipv6_http_fd > -1) && screen->httpPort) { - int enc_none = (enc_str && !strcmp(enc_str, "none")); - char *SPORT = " (single port)"; - if (use_openssl && ! enc_none) { - announce_http(screen->port, 1, listen_str, SPORT); - if (https_port_num >= 0) { - announce_http(https_port_num, 1, - listen_str, ""); - } - announce_http(screen->httpPort, 2, listen_str, ""); - } else if (use_stunnel) { - char pmsg[100]; - pmsg[0] = '\0'; - if (stunnel_port) { - sprintf(pmsg, "?PORT=%d", stunnel_port); - } - announce_http(screen->httpPort, 2, listen_str, pmsg); - if (stunnel_http_port > 0) { - announce_http(stunnel_http_port, 1, NULL, pmsg); - } - if (enc_none) { - strcat(pmsg, SPORT); - announce_http(stunnel_port, 1, NULL, pmsg); - } - } else { - announce_http(screen->httpPort, 0, listen_str, ""); - if (enc_none) { - announce_http(screen->port, 1, NULL, SPORT); - } - } - } -} - -void do_mention_java_urls(void) { - if (! quiet && screen) { - /* XXX ipv6? */ - if (screen->httpListenSock > -1 && screen->httpPort) { - rfbLog("\n"); - rfbLog("The URLs printed out below ('Java ... viewer URL') can\n"); - rfbLog("be used for Java enabled Web browser connections.\n"); - if (!stunnel_port && enc_str && !strcmp(enc_str, "none")) { - ; - } else if (use_openssl || stunnel_port) { - rfbLog("Here are some additional possibilities:\n"); - rfbLog("\n"); - rfbLog("https://host:port/proxy.vnc (MUST be used if Web Proxy used)\n"); - rfbLog("\n"); - rfbLog("https://host:port/ultra.vnc (Use UltraVNC Java Viewer)\n"); - rfbLog("https://host:port/ultraproxy.vnc (Web Proxy with UltraVNC)\n"); - rfbLog("https://host:port/ultrasigned.vnc (Signed UltraVNC Filexfer)\n"); - rfbLog("\n"); - rfbLog("Where you replace \"host:port\" with that printed below, or\n"); - rfbLog("whatever is needed to reach the host e.g. Internet IP number\n"); - rfbLog("\n"); - rfbLog("Append ?GET=1 to a URL for faster loading or supply:\n"); - rfbLog("-env X11VNC_EXTRA_HTTPS_PARAMS='?GET=1' to cmdline.\n"); - } - } - rfbLog("\n"); - } -} - -void set_vnc_desktop_name(void) { - sprintf(vnc_desktop_name, "unknown"); - if (inetd) { - sprintf(vnc_desktop_name, "%s/inetd-no-further-clients", - this_host()); - } - if (remote_direct) { - return; - } - if (screen->port) { - - do_mention_java_urls(); - - if (use_openssl) { - announce(screen->port, 1, listen_str); - } else { - announce(screen->port, 0, listen_str); - } - if (stunnel_port) { - announce(stunnel_port, 1, NULL); - } - - do_announce_http(); - - fflush(stderr); - if (inetd) { - ; /* should not occur (port != 0) */ - } else { - fprintf(stdout, "PORT=%d\n", screen->port); - if (stunnel_port) { - fprintf(stdout, "SSLPORT=%d\n", stunnel_port); - } else if (use_openssl) { - if (enc_str && !strcmp(enc_str, "none")) { - ; - } else if (enc_str) { - fprintf(stdout, "ENCPORT=%d\n", screen->port); - } else { - fprintf(stdout, "SSLPORT=%d\n", screen->port); - } - } - fflush(stdout); - if (flagfile) { - FILE *flag = fopen(flagfile, "w"); - if (flag) { - fprintf(flag, "PORT=%d\n",screen->port); - if (stunnel_port) { - fprintf(flag, "SSL_PORT=%d\n", - stunnel_port); - } - fflush(flag); - fclose(flag); - } else { - rfbLog("could not open flag file: %s\n", - flagfile); - } - } - if (rm_flagfile) { - int create = 0; - struct stat sb; - if (strstr(rm_flagfile, "create:") == rm_flagfile) { - char *s = rm_flagfile; - create = 1; - rm_flagfile = strdup(rm_flagfile + strlen("create:")); - free(s); - } - if (strstr(rm_flagfile, "nocreate:") == rm_flagfile) { - char *s = rm_flagfile; - create = 0; - rm_flagfile = strdup(rm_flagfile + strlen("nocreate:")); - free(s); - } else if (stat(rm_flagfile, &sb) != 0) { - create = 1; - } - if (create) { - FILE *flag = fopen(rm_flagfile, "w"); - if (flag) { - fprintf(flag, "%d\n", getpid()); - fclose(flag); - } - } - } - } - fflush(stdout); - } -} - -static void check_cursor_changes(void) { - static double last_push = 0.0; - - if (unixpw_in_progress) return; - - cursor_changes += check_x11_pointer(); - - if (cursor_changes) { - double tm, max_push = 0.125, multi_push = 0.01, wait = 0.02; - int cursor_shape, dopush = 0, link, latency, netrate; - - if (! all_clients_initialized()) { - /* play it safe */ - return; - } - - if (0) cursor_shape = cursor_shape_updates_clients(screen); - - dtime0(&tm); - link = link_rate(&latency, &netrate); - if (link == LR_DIALUP) { - max_push = 0.2; - wait = 0.05; - } else if (link == LR_BROADBAND) { - max_push = 0.075; - wait = 0.05; - } else if (link == LR_LAN) { - max_push = 0.01; - } else if (latency < 5 && netrate > 200) { - max_push = 0.01; - } - - if (tm > last_push + max_push) { - dopush = 1; - } else if (cursor_changes > 1 && tm > last_push + multi_push) { - dopush = 1; - } - - if (dopush) { - mark_rect_as_modified(0, 0, 1, 1, 1); - fb_push_wait(wait, FB_MOD); - last_push = tm; - } else { - rfbPE(0); - } - } - cursor_changes = 0; -} - -/* - * These watch_loop() releated were moved from x11vnc.c so we could try - * to remove -O2 from its compilation. TDB new file, e.g. watch.c. - */ - -static void check_filexfer(void) { - static time_t last_check = 0; - rfbClientIteratorPtr iter; - rfbClientPtr cl; - int transferring = 0; - - if (time(NULL) <= last_check) { - return; - } - -#if 0 - if (getenv("NOFT")) { - return; - } -#endif - - iter = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(iter)) ) { - if (cl->fileTransfer.receiving) { - transferring = 1; - break; - } - if (cl->fileTransfer.sending) { - transferring = 1; - break; - } - } - rfbReleaseClientIterator(iter); - - if (transferring) { - double start = dnow(); - while (dnow() < start + 0.5) { - rfbCFD(5000); - rfbCFD(1000); - rfbCFD(0); - } - } else { - last_check = time(NULL); - } -} - -static void record_last_fb_update(void) { - static int rbs0 = -1; - static time_t last_call = 0; - time_t now = time(NULL); - int rbs = -1; - rfbClientIteratorPtr iter; - rfbClientPtr cl; - - if (last_fb_bytes_sent == 0) { - last_fb_bytes_sent = now; - last_call = now; - } - - if (now <= last_call + 1) { - /* check every second or so */ - return; - } - - if (unixpw_in_progress) return; - - last_call = now; - - if (! screen) { - return; - } - - iter = rfbGetClientIterator(screen); - while( (cl = rfbClientIteratorNext(iter)) ) { -#if 0 - rbs += cl->rawBytesEquivalent; -#else -#if LIBVNCSERVER_HAS_STATS - rbs += rfbStatGetSentBytesIfRaw(cl); -#endif -#endif - } - rfbReleaseClientIterator(iter); - - if (rbs != rbs0) { - rbs0 = rbs; - if (debug_tiles > 1) { - fprintf(stderr, "record_last_fb_update: %d %d\n", - (int) now, (int) last_fb_bytes_sent); - } - last_fb_bytes_sent = now; - } -} - - -static int choose_delay(double dt) { - static double t0 = 0.0, t1 = 0.0, t2 = 0.0, now; - static int x0, y0, x1, y1, x2, y2, first = 1; - int dx0, dy0, dx1, dy1, dm, i, msec = waitms; - double cut1 = 0.15, cut2 = 0.075, cut3 = 0.25; - double bogdown_time = 0.25, bave = 0.0; - int bogdown = 1, bcnt = 0; - int ndt = 8, nave = 3; - double fac = 1.0; - static int db = 0, did_set_defer = 0; - static double dts[8]; - static int link = LR_UNSET, latency = -1, netrate = -1; - static double last_link = 0.0; - - if (screen && did_set_defer) { - /* reset defer in case we changed it */ - screen->deferUpdateTime = defer_update; - } - if (waitms == 0) { - return waitms; - } - if (nofb) { - return waitms; - } - - if (first) { - for(i=0; i<ndt; i++) { - dts[i] = 0.0; - } - if (getenv("DEBUG_DELAY")) { - db = atoi(getenv("DEBUG_DELAY")); - } - if (getenv("SET_DEFER")) { - set_defer = atoi(getenv("SET_DEFER")); - } - first = 0; - } - - now = dnow(); - - if (now > last_link + 30.0 || link == LR_UNSET) { - link = link_rate(&latency, &netrate); - last_link = now; - } - - /* - * first check for bogdown, e.g. lots of activity, scrolling text - * from command output, etc. - */ - if (nap_ok) { - dt = 0.0; - } - if (! wait_bog) { - bogdown = 0; - - } else if (button_mask || now < last_keyboard_time + 2*bogdown_time) { - /* - * let scrolls & keyboard input through the normal way - * otherwise, it will likely just annoy them. - */ - bogdown = 0; - - } else if (dt > 0.0) { - /* - * inspect recent dt's: - * 0 1 2 3 4 5 6 7 dt - * ^ ^ ^ - */ - for (i = ndt - (nave - 1); i < ndt; i++) { - bave += dts[i]; - bcnt++; - if (dts[i] < bogdown_time) { - bogdown = 0; - break; - } - } - bave += dt; - bcnt++; - bave = bave / bcnt; - if (dt < bogdown_time) { - bogdown = 0; - } - } else { - bogdown = 0; - } - /* shift for next time */ - for (i = 0; i < ndt-1; i++) { - dts[i] = dts[i+1]; - } - dts[ndt-1] = dt; - -if (0 && dt > 0.0) fprintf(stderr, "dt: %.5f %.4f\n", dt, dnowx()); - if (bogdown) { - if (use_xdamage) { - /* DAMAGE can queue ~1000 rectangles for a scroll */ - clear_xdamage_mark_region(NULL, 0); - } - msec = (int) (1000 * 1.75 * bave); - if (dts[ndt - nave - 1] > 0.75 * bave) { - msec = 1.5 * msec; - set_xdamage_mark(0, 0, dpy_x, dpy_y); - } - if (msec > 1500) { - msec = 1500; - } - if (msec < waitms) { - msec = waitms; - } - db = (db || debug_tiles); - if (db) fprintf(stderr, "bogg[%d] %.3f %.3f %.3f %.3f\n", - msec, dts[ndt-4], dts[ndt-3], dts[ndt-2], dts[ndt-1]); - - return msec; - } - - /* next check for pointer motion, keystrokes, to speed up */ - t2 = dnow(); - x2 = cursor_x; - y2 = cursor_y; - - dx0 = nabs(x1 - x0); - dy0 = nabs(y1 - y0); - dx1 = nabs(x2 - x1); - dy1 = nabs(y2 - y1); - - /* bigger displacement for most recent dt: */ - if (dx1 > dy1) { - dm = dx1; - } else { - dm = dy1; - } - - if ((dx0 || dy0) && (dx1 || dy1)) { - /* if mouse moved the previous two times: */ - if (t2 < t0 + cut1 || t2 < t1 + cut2 || dm > 20) { - /* - * if within 0.15s(0) or 0.075s(1) or mouse - * moved > 20pixels, set and bump up the cut - * down factor. - */ - fac = wait_ui * 1.5; - } else if ((dx1 || dy1) && dm > 40) { - fac = wait_ui; - } else { - /* still 1.0? */ - if (db > 1) fprintf(stderr, "wait_ui: still 1.0\n"); - } - } else if ((dx1 || dy1) && dm > 40) { - /* if mouse moved > 40 last time: */ - fac = wait_ui; - } - - if (fac == 1.0 && t2 < last_keyboard_time + cut3) { - /* if typed in last 0.25s set wait_ui */ - fac = wait_ui; - } - if (fac != 1.0) { - if (link == LR_LAN || latency <= 3) { - fac *= 1.5; - } - } - - msec = (int) (((double) waitms) / fac); - if (msec == 0) { - msec = 1; - } - - if (set_defer && fac != 1.0 && screen) { - /* this is wait_ui mode, set defer to match wait: */ - if (set_defer >= 1) { - screen->deferUpdateTime = msec; - } else if (set_defer <= -1) { - screen->deferUpdateTime = 0; - } - if (nabs(set_defer) == 2) { - urgent_update = 1; - } - did_set_defer = 1; - } - - x0 = x1; - y0 = y1; - t0 = t1; - - x1 = x2; - y1 = y2; - t1 = t2; - - if (db > 1) fprintf(stderr, "wait: %2d defer[%02d]: %2d\n", msec, defer_update, screen->deferUpdateTime); - - return msec; -} - -/* - * main x11vnc loop: polls, checks for events, iterate libvncserver, etc. - */ -void watch_loop(void) { - int cnt = 0, tile_diffs = 0, skip_pe = 0, wait; - double tm, dtr, dt = 0.0; - time_t start = time(NULL); - - if (use_threads && !started_rfbRunEventLoop) { - started_rfbRunEventLoop = 1; - rfbRunEventLoop(screen, -1, TRUE); - } - - while (1) { - char msg[] = "new client: %s taking unixpw client off hold.\n"; - int skip_scan_for_updates = 0; - - got_user_input = 0; - got_pointer_input = 0; - got_local_pointer_input = 0; - got_pointer_calls = 0; - got_keyboard_input = 0; - got_keyboard_calls = 0; - urgent_update = 0; - - x11vnc_current = dnow(); - - if (! use_threads) { - dtime0(&tm); - if (! skip_pe) { - if (unixpw_in_progress) { - rfbClientPtr cl = unixpw_client; - if (cl && cl->onHold) { - rfbLog(msg, cl->host); - unixpw_client->onHold = FALSE; - } - } else { - measure_send_rates(1); - } - - unixpw_in_rfbPE = 1; - - /* - * do a few more since a key press may - * have induced a small change we want to - * see quickly (just 1 rfbPE will likely - * only process the subsequent "up" event) - */ - if (tm < last_keyboard_time + 0.20) { - rfbPE(0); - rfbPE(0); - rfbPE(-1); - rfbPE(0); - rfbPE(0); - } else { - if (extra_fbur > 0) { - int i; - for (i=0; i < extra_fbur; i++) { - rfbPE(0); - } - } - rfbPE(-1); - } - if (x11vnc_current < last_new_client + 0.5) { - urgent_update = 1; - } - - unixpw_in_rfbPE = 0; - - if (unixpw_in_progress) { - /* rfbPE loop until logged in. */ - skip_pe = 0; - check_new_clients(); - continue; - } else { - measure_send_rates(0); - fb_update_sent(NULL); - } - } else { - if (unixpw_in_progress) { - skip_pe = 0; - check_new_clients(); - continue; - } - } - dtr = dtime(&tm); - - if (! cursor_shape_updates) { - /* undo any cursor shape requests */ - disable_cursor_shape_updates(screen); - } - if (screen && screen->clientHead) { - int ret = check_user_input(dt, dtr, tile_diffs, &cnt); - /* true: loop back for more input */ - if (ret == 2) { - skip_pe = 1; - } - if (ret) { - if (debug_scroll) fprintf(stderr, "watch_loop: LOOP-BACK: %d\n", ret); - continue; - } - } - /* watch for viewonly input piling up: */ - if ((got_pointer_calls > got_pointer_input) || - (got_keyboard_calls > got_keyboard_input)) { - eat_viewonly_input(10, 3); - } - } else { - /* -threads here. */ - if (unixpw_in_progress) { - rfbClientPtr cl = unixpw_client; - if (cl && cl->onHold) { - rfbLog(msg, cl->host); - unixpw_client->onHold = FALSE; - } - } - if (use_xrecord) { - check_xrecord(); - } - if (wireframe && button_mask) { - check_wireframe(); - } - } - skip_pe = 0; - - if (shut_down) { - clean_up_exit(0); - } - - if (unixpw_in_progress) { - check_new_clients(); - continue; - } - - if (! urgent_update) { - if (do_copy_screen) { - do_copy_screen = 0; - copy_screen(); - } - - check_new_clients(); - check_ncache(0, 0); - check_xevents(0); - check_autorepeat(); - check_pm(); - check_filexfer(); - check_keycode_state(); - check_connect_inputs(); - check_gui_inputs(); - check_stunnel(); - check_openssl(); - check_https(); - record_last_fb_update(); - check_padded_fb(); - check_fixscreen(); - check_xdamage_state(); - check_xrecord_reset(0); - check_add_keysyms(); - check_new_passwds(0); -#ifdef ENABLE_GRABLOCAL - if (grab_local) { - check_local_grab(); - } -#endif - if (started_as_root) { - check_switched_user(); - } - - if (first_conn_timeout < 0) { - start = time(NULL); - first_conn_timeout = -first_conn_timeout; - } - } - - if (rawfb_vnc_reflect) { - static time_t lastone = 0; - if (time(NULL) > lastone + 10) { - lastone = time(NULL); - vnc_reflect_process_client(); - } - } - - if (first_conn_timeout) { - int t = first_conn_timeout; - if (!clients_served) { - if (time(NULL) - start > first_conn_timeout) { - rfbLog("No client after %d secs.\n", t); - shut_down = 1; - } - } else { - if (!client_normal_count) { - if (time(NULL) - start > t + 3) { - rfbLog("No valid client after %d secs.\n", t + 3); - shut_down = 1; - } - } - } - } - - if (! screen || ! screen->clientHead) { - /* waiting for a client */ - usleep(200 * 1000); - continue; - } - - if (first_conn_timeout && all_clients_initialized()) { - first_conn_timeout = 0; - } - - if (nofb) { - /* no framebuffer polling needed */ - if (cursor_pos_updates) { - check_x11_pointer(); - } -#ifdef MACOSX - else check_x11_pointer(); -#endif - continue; - } - if (x11vnc_current < last_new_client + 0.5 && !all_clients_initialized()) { - continue; - } - if (subwin && freeze_when_obscured) { - /* XXX not working */ - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - check_xevents(0); - if (subwin_obscured) { - skip_scan_for_updates = 1; - } - } - - if (skip_scan_for_updates) { - ; - } else if (button_mask && (!show_dragging || pointer_mode == 0)) { - /* - * if any button is pressed in this mode do - * not update rfb screen, but do flush the - * X11 display. - */ - X_LOCK; - XFlush_wr(dpy); - X_UNLOCK; - dt = 0.0; - } else { - static double last_dt = 0.0; - double xdamage_thrash = 0.4; - static int tilecut = -1; - - check_cursor_changes(); - - /* for timing the scan to try to detect thrashing */ - - if (use_xdamage && last_dt > xdamage_thrash) { - clear_xdamage_mark_region(NULL, 0); - } - - if (unixpw_in_progress) continue; - - if (rawfb_vnc_reflect) { - vnc_reflect_process_client(); - } - - dtime0(&tm); - -#if !NO_X11 - if (xrandr_present && !xrandr && xrandr_maybe) { - int delay = 180; - /* there may be xrandr right after xsession start */ - if (tm < x11vnc_start + delay || tm < last_client + delay) { - int tw = 20; - if (auth_file != NULL) { - tw = 120; - } - X_LOCK; - if (tm < x11vnc_start + tw || tm < last_client + tw) { - XSync(dpy, False); - } else { - XFlush_wr(dpy); - } - X_UNLOCK; - } - X_LOCK; - check_xrandr_event("before-scan"); - X_UNLOCK; - } -#endif - if (use_snapfb) { - int t, tries = 3; - copy_snap(); - for (t=0; t < tries; t++) { - tile_diffs = scan_for_updates(0); - } - } else { - tile_diffs = scan_for_updates(0); - } - dt = dtime(&tm); - if (! nap_ok) { - last_dt = dt; - } - - if (tilecut < 0) { - if (getenv("TILECUT")) { - tilecut = atoi(getenv("TILECUT")); - } - if (tilecut < 0) tilecut = 4; - } - - if ((debug_tiles || debug_scroll > 1 || debug_wireframe > 1) - && (tile_diffs > tilecut || debug_tiles > 1)) { - double rate = (tile_x * tile_y * bpp/8 * tile_diffs) / dt; - fprintf(stderr, "============================= TILES: %d dt: %.4f" - " t: %.4f %.2f MB/s nap_ok: %d\n", tile_diffs, dt, - tm - x11vnc_start, rate/1000000.0, nap_ok); - } - - } - - /* sleep a bit to lessen load */ - wait = choose_delay(dt); - - if (urgent_update) { - ; - } else if (wait > 2*waitms) { - /* bog case, break it up */ - nap_sleep(wait, 10); - } else { - double t1, t2; - int idt; - if (extra_fbur > 0) { - int i; - for (i=0; i <= extra_fbur; i++) { - int r = rfbPE(0); - if (!r) break; - } - } - - /* sometimes the sleep is too short, so measure it: */ - t1 = dnow(); - usleep(wait * 1000); - t2 = dnow(); - - idt = (int) (1000. * (t2 - t1)); - if (idt > 0 && idt < wait) { - /* try to sleep the remainder */ - usleep((wait - idt) * 1000); - } - } - - cnt++; - } -} - - |