10
#include "userinput.h"
17
#include "connections.h"
21
#include "sslhelper.h"
30
#include <rfb/rfbclient.h>
32
void set_greyscale_colormap(void);
33
void set_hi240_colormap(void);
34
void unset_colormap(void);
35
void set_colormap(int reset);
36
void set_nofb_params(int restore);
37
void set_raw_fb_params(int restore);
38
void do_new_fb(int reset_mem);
39
void free_old_fb(void);
40
void check_padded_fb(void);
41
void install_padded_fb(char *geom);
42
XImage *initialize_xdisplay_fb(void);
43
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
44
int *nomult4, int *pad, int *interpolate, int *numer, int *denom);
45
int parse_rotate_string(char *str, int *mode);
46
int scale_round(int len, double fac);
47
void initialize_screen(int *argc, char **argv, XImage *fb);
48
void set_vnc_desktop_name(void);
49
void announce(int lport, int ssl, char *iface);
52
char *vnc_reflect_guess(char *str, char **raw_fb_addr);
53
void vnc_reflect_process_client(void);
54
rfbBool vnc_reflect_send_pointer(int x, int y, int mask);
55
rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down);
56
rfbBool vnc_reflect_send_cuttext(char *str, int len);
59
static void debug_colormap(XImage *fb);
60
static void set_visual(char *str);
61
static void nofb_hook(rfbClientPtr cl);
62
static void remove_fake_fb(void);
63
static void install_fake_fb(int w, int h, int bpp);
64
static void initialize_snap_fb(void);
65
XImage *initialize_raw_fb(int);
66
static void initialize_clipshift(void);
67
static int wait_until_mapped(Window win);
68
static void setup_scaling(int *width_in, int *height_in);
71
int rawfb_dev_video = 0;
72
int rawfb_vnc_reflect = 0;
75
* X11 and rfb display/screen related routines
79
* Some handling of 8bpp PseudoColor colormaps. Called for initializing
80
* the clients and dynamically if -flashcmap is specified.
84
void set_greyscale_colormap(void) {
89
if (screen->colourMap.data.shorts) {
90
free(screen->colourMap.data.shorts);
91
screen->colourMap.data.shorts = NULL;
94
if (0) fprintf(stderr, "set_greyscale_colormap: %s\n", raw_fb_pixfmt);
95
screen->colourMap.count = NCOLOR;
96
screen->serverFormat.trueColour = FALSE;
97
screen->colourMap.is16 = TRUE;
98
screen->colourMap.data.shorts = (unsigned short *)
99
malloc(3*sizeof(unsigned short) * NCOLOR);
101
for(i = 0; i < NCOLOR; i++) {
102
unsigned short lvl = i * 256;
104
screen->colourMap.data.shorts[i*3+0] = lvl;
105
screen->colourMap.data.shorts[i*3+1] = lvl;
106
screen->colourMap.data.shorts[i*3+2] = lvl;
109
rfbSetClientColourMaps(screen, 0, NCOLOR);
112
/* this is specific to bttv rf tuner card */
113
void set_hi240_colormap(void) {
118
if (0) fprintf(stderr, "set_hi240_colormap: %s\n", raw_fb_pixfmt);
119
if (screen->colourMap.data.shorts) {
120
free(screen->colourMap.data.shorts);
121
screen->colourMap.data.shorts = NULL;
124
screen->colourMap.count = 256;
125
screen->serverFormat.trueColour = FALSE;
126
screen->colourMap.is16 = TRUE;
127
screen->colourMap.data.shorts = (unsigned short *)
128
calloc(3*sizeof(unsigned short) * 256, 1);
130
for(i = 0; i < 225; i++) {
133
r = ( (i/5) % 5 ) * 255.0 / 4 + 0.5;
134
g = ( (i/25) ) * 255.0 / 8 + 0.5;
135
b = ( i % 5 ) * 255.0 / 4 + 0.5;
137
screen->colourMap.data.shorts[(i+16)*3+0] = (unsigned short) (r * 256);
138
screen->colourMap.data.shorts[(i+16)*3+1] = (unsigned short) (g * 256);
139
screen->colourMap.data.shorts[(i+16)*3+2] = (unsigned short) (b * 256);
142
rfbSetClientColourMaps(screen, 0, 256);
144
void unset_colormap(void) {
148
if (screen->colourMap.data.shorts) {
149
free(screen->colourMap.data.shorts);
150
screen->colourMap.data.shorts = NULL;
152
screen->serverFormat.trueColour = TRUE;
153
if (0) fprintf(stderr, "unset_colormap: %s\n", raw_fb_pixfmt);
156
void set_colormap(int reset) {
162
static XColor color[NCOLOR], prev[NCOLOR];
165
int i, ncells, diffs = 0;
169
if (screen->colourMap.data.shorts) {
170
free(screen->colourMap.data.shorts);
171
screen->colourMap.data.shorts = NULL;
174
if (0) fprintf(stderr, "unset_colormap: %d\n", reset);
177
screen->colourMap.count = NCOLOR;
178
screen->serverFormat.trueColour = FALSE;
179
screen->colourMap.is16 = TRUE;
180
screen->colourMap.data.shorts = (unsigned short *)
181
malloc(3*sizeof(unsigned short) * NCOLOR);
184
for (i=0; i < NCOLOR; i++) {
185
prev[i].red = color[i].red;
186
prev[i].green = color[i].green;
187
prev[i].blue = color[i].blue;
194
cmap = DefaultColormap(dpy, scr);
195
ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr));
196
vis = default_visual;
199
XWindowAttributes attr;
201
if (XGetWindowAttributes(dpy, window, &attr)) {
202
cmap = attr.colormap;
204
ncells = vis->map_entries;
208
if (ncells != NCOLOR) {
209
if (init && ! quiet) {
210
rfbLog("set_colormap: number of cells is %d "
211
"instead of %d.\n", ncells, NCOLOR);
214
screen->colourMap.count = ncells;
218
if (flash_cmap && ! init) {
219
XWindowAttributes attr;
224
while (c && tries++ < 16) {
225
c = query_pointer(c);
226
if (valid_window(c, &attr, 0)) {
227
if (attr.colormap && attr.map_installed) {
228
cmap = attr.colormap;
230
ncells = vis->map_entries;
238
if (ncells > NCOLOR && ! quiet) {
239
rfbLog("set_colormap: big problem: ncells=%d > %d\n",
243
if (vis->class == TrueColor || vis->class == DirectColor) {
245
* Kludge to make 8bpp TrueColor & DirectColor be like
246
* the StaticColor map. The ncells = 8 is "8 per subfield"
247
* mentioned in xdpyinfo. Looks OK... perhaps fortuitously.
249
if (ncells == 8 && ! shift_cmap) {
254
for (i=0; i < ncells; i++) {
259
XQueryColors(dpy, cmap, color, ncells);
263
for(i = ncells - 1; i >= 0; i--) {
264
int k = i + shift_cmap;
266
screen->colourMap.data.shorts[i*3+0] = color[i].red;
267
screen->colourMap.data.shorts[i*3+1] = color[i].green;
268
screen->colourMap.data.shorts[i*3+2] = color[i].blue;
270
if (prev[i].red != color[i].red ||
271
prev[i].green != color[i].green ||
272
prev[i].blue != color[i].blue ) {
276
if (shift_cmap && k >= 0 && k < NCOLOR) {
277
/* kludge to copy the colors to higher pixel values */
278
screen->colourMap.data.shorts[k*3+0] = color[i].red;
279
screen->colourMap.data.shorts[k*3+1] = color[i].green;
280
screen->colourMap.data.shorts[k*3+2] = color[i].blue;
284
if (diffs && ! init) {
285
if (! all_clients_initialized()) {
286
rfbLog("set_colormap: warning: sending cmap "
287
"with uninitialized clients.\n");
290
rfbSetClientColourMaps(screen, 0, NCOLOR);
292
rfbSetClientColourMaps(screen, 0, ncells);
300
static void debug_colormap(XImage *fb) {
301
static int debug_cmap = -1;
302
int i, k, histo[NCOLOR];
304
if (debug_cmap < 0) {
305
if (getenv("DEBUG_CMAP") != NULL) {
317
if (fb->bits_per_pixel > 8) {
321
for (i=0; i < NCOLOR; i++) {
324
for (k = 0; k < fb->width * fb->height; k++) {
326
char c = *(fb->data + k);
328
n = (unsigned char) c;
331
fprintf(stderr, "\nColormap histogram for current screen contents:\n");
332
for (i=0; i < NCOLOR; i++) {
333
unsigned short r = screen->colourMap.data.shorts[i*3+0];
334
unsigned short g = screen->colourMap.data.shorts[i*3+1];
335
unsigned short b = screen->colourMap.data.shorts[i*3+2];
337
fprintf(stderr, " %03d: %7d %04x/%04x/%04x", i, histo[i],
339
if ((i+1) % 2 == 0) {
340
fprintf(stderr, "\n");
343
fprintf(stderr, "\n");
347
* Experimental mode to force the visual of the window instead of querying
348
* it. Used for testing, overriding some rare cases (win2vnc), and for
349
* -overlay . Input string can be a decimal or 0x hex or something like
350
* TrueColor or TrueColor:24 to force a depth as well.
352
* visual_id and possibly visual_depth are set.
354
static void set_visual(char *str) {
360
int vis, vdepth, defdepth;
362
char *p, *vstring = strdup(str);
366
defdepth = DefaultDepth(dpy, scr);
367
visual_id = (VisualID) 0;
370
if (!strcmp(vstring, "ignore") || !strcmp(vstring, "default")
371
|| !strcmp(vstring, "")) {
376
/* set visual depth */
377
if ((p = strchr(vstring, ':')) != NULL) {
378
visual_depth = atoi(p+1);
380
vdepth = visual_depth;
385
fprintf(stderr, "\nVisual Info:\n");
386
fprintf(stderr, " set_visual(\"%s\")\n", str);
387
fprintf(stderr, " visual_depth: %d\n", vdepth);
390
/* set visual id number */
391
if (strcmp(vstring, "StaticGray") == 0) {
393
} else if (strcmp(vstring, "GrayScale") == 0) {
395
} else if (strcmp(vstring, "StaticColor") == 0) {
397
} else if (strcmp(vstring, "PseudoColor") == 0) {
399
} else if (strcmp(vstring, "TrueColor") == 0) {
401
} else if (strcmp(vstring, "DirectColor") == 0) {
405
if (sscanf(vstring, "0x%x", &v_in) != 1) {
406
if (sscanf(vstring, "%u", &v_in) == 1) {
407
visual_id = (VisualID) v_in;
411
rfbLog("invalid -visual arg: %s\n", vstring);
415
visual_id = (VisualID) v_in;
420
if (! quiet) fprintf(stderr, " visual: %d\n", vis);
421
if (XMatchVisualInfo(dpy, scr, visual_depth, vis, &vinfo)) {
423
} else if (XMatchVisualInfo(dpy, scr, defdepth, vis, &vinfo)) {
427
rfbLog("could not find visual: %s\n", vstring);
433
/* set numerical visual id. */
434
visual_id = vinfo.visualid;
438
void set_nofb_params(int restore) {
439
static int first = 1;
440
static int save[100];
441
static char *scroll = NULL;
446
save[i++] = use_xfixes;
447
save[i++] = use_xdamage;
448
save[i++] = use_xrecord;
449
save[i++] = wireframe;
450
save[i++] = use_solid_bg;
452
save[i++] = overlay_cursor;
453
save[i++] = using_shm;
454
save[i++] = single_copytile;
455
save[i++] = take_naps;
456
save[i++] = measure_speeds;
457
save[i++] = grab_buster;
458
save[i++] = show_cursor;
459
save[i++] = cursor_shape_updates;
460
save[i++] = cursor_pos_updates;
463
scroll = scroll_copyrect;
467
use_xfixes = save[i++];
468
use_xdamage = save[i++];
469
use_xrecord = save[i++];
470
wireframe = save[i++];
471
use_solid_bg = save[i++];
473
overlay_cursor = save[i++];
474
using_shm = save[i++];
475
single_copytile = save[i++];
476
take_naps = save[i++];
477
measure_speeds = save[i++];
478
grab_buster = save[i++];
479
show_cursor = save[i++];
480
cursor_shape_updates = save[i++];
481
cursor_pos_updates = save[i++];
484
scroll_copyrect = scroll;
486
if (cursor_shape_updates) {
487
restore_cursor_shape_updates(screen);
489
initialize_cursors_mode();
509
/* got_grab_buster? */
513
show_multiple_cursors = 0;
514
cursor_shape_updates = 0;
515
if (! got_cursorpos) {
516
cursor_pos_updates = 0;
521
scroll_copyrect = "never";
524
rfbLog("disabling: xfixes, xdamage, solid, overlay, shm,\n");
525
rfbLog(" wireframe, scrollcopyrect, ncache,\n");
526
rfbLog(" noonetile, nap, cursor, %scursorshape\n",
527
got_cursorpos ? "" : "cursorpos, " );
528
rfbLog(" in -nofb mode.\n");
532
static char *raw_fb_orig_dpy = NULL;
534
void set_raw_fb_params(int restore) {
535
static int first = 1;
536
static int vo0, us0, sm0, ws0, wp0, wc0, wb0, na0, tn0;
537
static int xr0, xrm0, sb0, re0;
541
* set turn off a bunch of parameters not compatible with
542
* -rawfb mode: 1) ignoring the X server 2) ignoring user input.
546
/* at least save the initial settings... */
548
ws0 = watch_selection;
550
wc0 = watch_clipboard;
561
mc0 = multiple_cursors_mode;
568
watch_selection = ws0;
570
watch_clipboard = wc0;
581
multiple_cursors_mode = mc0;
583
if (! dpy && raw_fb_orig_dpy) {
584
dpy = XOpenDisplay_wr(raw_fb_orig_dpy);
586
if (! quiet) rfbLog("reopened DISPLAY: %s\n",
588
scr = DefaultScreen(dpy);
589
rootwin = RootWindow(dpy, scr);
592
if (! quiet) rfbLog("WARNING: failed to reopen "
593
"DISPLAY: %s\n", raw_fb_orig_dpy);
600
rfbLog("set_raw_fb_params: modifying settings for "
604
if (got_noviewonly) {
606
* The user input parameters are not unset under
607
* -noviewonly... this usage should be very rare
608
* (i.e. rawfb but also send user input to the X
609
* display, most likely using /dev/fb0 for some reason...)
612
rfbLog("rawfb: -noviewonly mode: still sending mouse and\n");
613
rfbLog("rawfb: keyboard input to the X DISPLAY!!\n");
618
if (! view_only && ! pipeinput_str) {
619
if (! quiet) rfbLog(" rawfb: setting view_only\n");
623
if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
625
} else if (watch_selection) {
626
if (verbose) rfbLog(" rawfb: turning off "
627
"watch_selection\n");
631
if (verbose) rfbLog(" rawfb: turning off "
635
if (watch_clipboard) {
636
if (verbose) rfbLog(" rawfb: turning off "
637
"watch_clipboard\n");
641
if (verbose) rfbLog(" rawfb: turning off watch_bell\n");
645
if (verbose) rfbLog(" rawfb: turning off "
650
if (verbose) rfbLog(" rawfb: turning off "
655
if (raw_fb_str && strstr(raw_fb_str, "vnc") == raw_fb_str) {
658
multiple_cursors_mode = strdup("arrow");
663
if (verbose) rfbLog(" rawfb: turning off using_shm\n");
667
if (verbose) rfbLog(" rawfb: turning off take_naps\n");
671
if (verbose) rfbLog(" rawfb: turning off xrandr\n");
675
if (verbose) rfbLog(" rawfb: turning off xrandr_maybe\n");
679
if (verbose) rfbLog(" rawfb: turning off xrecord\n");
685
* Presumably under -nofb the clients will never request the framebuffer.
686
* However, we have gotten such a request... so let's just give them
687
* the current view on the display. n.b. x2vnc and perhaps win2vnc
688
* requests a 1x1 pixel for some workaround so sadly this evidently
689
* nearly always happens.
691
static void nofb_hook(rfbClientPtr cl) {
695
rfbLog("framebuffer requested in -nofb mode by client %s\n", cl->host);
698
if (raw_fb && ! dpy) {
700
fb->data = (char *)malloc(32);
702
int use_real_ximage = 0;
703
if (use_real_ximage) {
704
fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes, ZPixmap);
707
fb->data = (char *) calloc(dpy_x*dpy_y*bpp/8, 1);
712
screen->frameBuffer = rfb_fb;
713
screen->displayHook = NULL;
716
void free_old_fb(void) {
718
int i, j, nfb = 0, db = 0;
720
fbs[nfb++] = main_fb; main_fb = NULL;
721
fbs[nfb++] = rfb_fb; rfb_fb = NULL;
722
fbs[nfb++] = cmap8to24_fb; cmap8to24_fb = NULL;
723
fbs[nfb++] = snap_fb; snap_fb = NULL;
724
fbs[nfb++] = rot_fb; rot_fb = NULL;
725
fbs[nfb++] = raw_fb; raw_fb = NULL;
727
for (i=0; i < nfb; i++) {
730
if (! fb || fb < (char *) 0x10) {
733
for (j=0; j < i; j++) {
740
if (db) fprintf(stderr, "free: %i %p\n", i, fb);
743
if (db) fprintf(stderr, "skip: %i %p\n", i, fb);
748
void do_new_fb(int reset_mem) {
751
/* for threaded we really should lock libvncserver out. */
753
rfbLog("warning: changing framebuffers while threaded may\n");
754
rfbLog(" not work, do not use -threads if problems arise.\n");
757
if (reset_mem == 1) {
758
/* reset_mem == 2 is a hack for changing users... */
765
fb = initialize_xdisplay_fb();
767
initialize_screen(NULL, NULL, fb);
771
initialize_blackouts_and_xinerama();
772
initialize_polling_images();
779
static void remove_fake_fb(void) {
783
rfbLog("removing fake fb: 0x%x\n", fake_fb);
788
* fake_fb is freed in do_new_fb(), but we set to NULL here to
789
* indicate it is gone.
794
static void install_fake_fb(int w, int h, int bpp) {
802
fake_fb = (char *) calloc(w*h*bpp/8, 1);
804
rfbLog("could not create fake fb: %dx%d %d\n", w, h, bpp);
807
bpc = guess_bits_per_color(bpp);
808
rfbLog("installing fake fb: %dx%d %d\n", w, h, bpp);
809
rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n",
810
screen, fake_fb, w, h, bpc, 1, bpp/8);
812
rfbNewFramebuffer(screen, fake_fb, w, h, bpc, 1, bpp/8);
815
void check_padded_fb(void) {
819
if (unixpw_in_progress) return;
821
if (time(NULL) > pad_geometry_time+1 && all_clients_initialized()) {
826
void install_padded_fb(char *geom) {
829
if (! geom || *geom == '\0') {
831
} else if (sscanf(geom, "%dx%d", &w, &h) != 2) {
841
rfbLog("skipping invalid pad geometry: '%s'\n", NONUL(geom));
844
install_fake_fb(w, h, bpp);
845
pad_geometry_time = time(NULL);
848
static void initialize_snap_fb(void) {
853
snap = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
855
snap_fb = snap->data;
859
static rfbClient* client = NULL;
861
void vnc_reflect_bell(rfbClient *cl) {
864
if (unixpw_in_progress) {
867
if (! all_clients_initialized()) {
868
rfbLog("vnc_reflect_bell: not sending bell: "
869
"uninitialized clients\n");
871
if (screen && client_count) {
878
void vnc_reflect_recv_cuttext(rfbClient *cl, const char *str, int len) {
880
if (unixpw_in_progress) {
883
if (! watch_selection) {
886
if (! all_clients_initialized()) {
887
rfbLog("vnc_reflect_recv_cuttext: no send: uninitialized clients\n");
888
return; /* some clients initializing, cannot send */
890
rfbSendServerCutText(screen, (char *)str, len);
893
void vnc_reflect_got_update(rfbClient *cl, int x, int y, int w, int h) {
896
static int first = 1;
898
collect_non_X_xdamage(-1, -1, -1, -1, 0);
901
collect_non_X_xdamage(x, y, w, h, 1);
905
void vnc_reflect_got_cursorshape(rfbClient *cl, int xhot, int yhot, int width, int height, int bytesPerPixel) {
906
static int serial = 1;
909
unsigned long r, g, b;
911
unsigned long red_mask, green_mask, blue_mask;
914
if (unixpw_in_progress) {
917
if (! all_clients_initialized()) {
918
rfbLog("vnc_reflect_got_copyshape: no send: uninitialized clients\n");
919
return; /* some clients initializing, cannot send */
921
if (! client->rcSource) {
924
if (bytesPerPixel != 1 && bytesPerPixel != 2 && bytesPerPixel != 4) {
928
red_mask = (client->format.redMax << client->format.redShift);
929
green_mask = (client->format.greenMax << client->format.greenShift);
930
blue_mask = (client->format.blueMax << client->format.blueShift);
932
pixels = (char *)malloc(4*width*height);
933
for (j=0; j<height; j++) {
934
for (i=0; i<width; i++) {
938
if (bytesPerPixel == 1) {
939
unsigned char* p = (unsigned char *) client->rcSource;
940
ui = (unsigned long) *(p + j * width + i);
941
} else if (bytesPerPixel == 2) {
942
unsigned short* p = (unsigned short *) client->rcSource;
943
ui = (unsigned long) *(p + j * width + i);
944
} else if (bytesPerPixel == 4) {
945
unsigned int* p = (unsigned int *) client->rcSource;
946
ui = (unsigned long) *(p + j * width + i);
948
r = (red_mask & ui) >> client->format.redShift;
949
g = (green_mask & ui) >> client->format.greenShift;
950
b = (blue_mask & ui) >> client->format.blueShift;
952
r = (255 * r) / client->format.redMax;
953
g = (255 * g) / client->format.greenMax;
954
b = (255 * b) / client->format.blueMax;
956
ui = (r << 16 | g << 8 | b << 0) ;
958
uic = (unsigned char *)client->rcMask;
959
m = (int) *(uic + j * width + i);
963
uip = (unsigned int *)pixels;
964
*(uip + j * width + i) = ui;
968
store_cursor(serial++, (unsigned long*) pixels, width, height, 32, xhot, yhot);
970
set_cursor(cursor_x, cursor_y, get_which_cursor());
973
void vnc_reflect_got_copyrect(rfbClient *cl, int src_x, int src_y, int w, int h, int dest_x, int dest_y) {
976
static int last_dx = 0, last_dy = 0;
978
if (unixpw_in_progress) {
981
if (! all_clients_initialized()) {
982
rfbLog("vnc_reflect_got_copyrect: no send: uninitialized clients\n");
983
return; /* some clients initializing, cannot send */
987
if (dx != last_dx || dy != last_dy) {
988
rc = fb_push_wait(0.05, FB_COPY|FB_MOD);
990
if (0) fprintf(stderr, "vnc_reflect_got_copyrect: %dx%d+%d+%d %d %d rc=%d\n", dest_x, dest_y, w, h, dx, dy, rc);
991
reg = sraRgnCreateRect(dest_x, dest_y, dest_x + w, dest_y + h);
992
do_copyregion(reg, dx, dy, 0);
999
rfbBool vnc_reflect_resize(rfbClient *cl) {
1000
static int first = 1;
1001
if(cl->frameBuffer) {
1002
free(cl->frameBuffer);
1004
cl->frameBuffer= malloc(cl->width * cl->height * cl->format.bitsPerPixel/8);
1009
return cl->frameBuffer ? TRUE : FALSE;
1012
char *vnc_reflect_guess(char *str, char **raw_fb_addr) {
1014
static int first = 1;
1015
char *hp = str + strlen("vnc:");
1020
char *str0 = strdup(str);
1022
if (client == NULL) {
1023
client = rfbGetClient(8, 3, 4);
1026
rfbLog("rawfb: %s\n", str);
1028
at = strchr(hp, '@');
1034
client->appData.useRemoteCursor = TRUE;
1035
client->Bell = vnc_reflect_bell;
1036
client->GotXCutText = vnc_reflect_recv_cuttext;
1037
client->GotCopyRect = vnc_reflect_got_copyrect;
1038
client->GotCursorShape = vnc_reflect_got_cursorshape;
1039
client->MallocFrameBuffer = vnc_reflect_resize;
1040
client->canHandleNewFBSize = TRUE;
1041
client->GotFrameBufferUpdate = vnc_reflect_got_update;
1044
argv[argc++] = "x11vnc_rawfb_vnc";
1045
if (strstr(hp, "listen") == hp) {
1046
char *q = strchr(hp, ':');
1047
argv[argc++] = strdup("-listen");
1049
client->listenPort = atoi(q+1);
1051
client->listenPort = LISTEN_PORT_OFFSET;
1054
argv[argc++] = strdup(hp);
1057
if (! rfbInitClient(client, &argc, argv)) {
1058
rfbLog("vnc_reflector failed for: %s\n", str0);
1064
sprintf(str2, "map:/dev/null@%s", at);
1066
unsigned long red_mask, green_mask, blue_mask;
1067
red_mask = (client->format.redMax << client->format.redShift);
1068
green_mask = (client->format.greenMax << client->format.greenShift);
1069
blue_mask = (client->format.blueMax << client->format.blueShift);
1070
sprintf(str2, "map:/dev/null@%dx%dx%d:0x%lx/0x%lx/0x%lx",
1071
client->width, client->height, client->format.bitsPerPixel,
1072
red_mask, green_mask, blue_mask);
1074
*raw_fb_addr = (char *) client->frameBuffer;
1078
setup_cursors_and_push();
1080
for (i=0; i<10; i++) {
1081
vnc_reflect_process_client();
1086
return strdup(str2);
1089
rfbBool vnc_reflect_send_pointer(int x, int y, int mask) {
1093
got_pointer_input++;
1094
last_pointer_time = time(NULL);
1097
if (cursor_x != x || cursor_y != y) {
1098
last_pointer_motion_time = dnow();
1104
/* record the x, y position for the rfb screen as well. */
1105
cursor_position(x, y);
1107
/* change the cursor shape if necessary */
1108
rc = set_cursor(x, y, get_which_cursor());
1109
cursor_changes += rc;
1111
return SendPointerEvent(client, x, y, mask);
1114
rfbBool vnc_reflect_send_key(uint32_t key, rfbBool down) {
1115
return SendKeyEvent(client, key, down);
1118
rfbBool vnc_reflect_send_cuttext(char *str, int len) {
1119
return SendClientCutText(client, str, len);
1122
void vnc_reflect_process_client(void) {
1124
if (client == NULL) {
1127
num = WaitForMessage(client, 1000);
1129
if (!HandleRFBServerMessage(client)) {
1130
rfbLog("vnc_reflect_process_client: read failure to server\n");
1137
#define RAWFB_MMAP 1
1138
#define RAWFB_FILE 2
1141
XImage *initialize_raw_fb(int reset) {
1143
int w, h, b, shmid = 0;
1144
unsigned long rm = 0, gm = 0, bm = 0, tm;
1145
static XImage ximage_struct; /* n.b.: not (XImage *) */
1146
static XImage ximage_struct_snap;
1147
int closedpy = 1, i, m, db = 0;
1150
char *unlink_me = NULL;
1152
static char *last_file = NULL;
1153
static int last_mode = 0;
1155
if (reset && last_mode) {
1157
if (last_mode != RAWFB_MMAP && last_mode != RAWFB_FILE) {
1160
if (last_mode == RAWFB_MMAP) {
1161
munmap(raw_fb_addr, raw_fb_mmap);
1163
if (raw_fb_fd >= 0) {
1167
if (db) fprintf(stderr, "initialize_raw_fb reset\n");
1170
if (rawfb_dev_video) {
1171
fd = open(last_file, O_RDWR);
1174
fd = open(last_file, O_RDONLY);
1178
rfbLog("failed to rawfb file: %s\n", last_file);
1179
rfbLogPerror("open");
1183
if (last_mode == RAWFB_MMAP) {
1184
raw_fb_addr = mmap(0, raw_fb_mmap, PROT_READ,
1187
if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) {
1189
rfbLog("failed to mmap file: %s\n", last_file);
1190
rfbLog(" raw_fb_addr: %p\n", raw_fb_addr);
1191
rfbLogPerror("mmap");
1199
if (raw_fb_addr != NULL && macosx_console && raw_fb_addr == macosx_get_fb_addr()) {
1204
if (raw_fb_addr || raw_fb_seek) {
1207
#if LIBVNCSERVER_HAVE_MMAP
1208
} else if (raw_fb_mmap) {
1209
munmap(raw_fb_addr, raw_fb_mmap);
1210
if (raw_fb_fd >= 0) {
1215
} else if (raw_fb_seek) {
1216
if (raw_fb_fd >= 0) {
1229
/* testing aliases */
1230
if (!strcasecmp(raw_fb_str, "NULL") || !strcasecmp(raw_fb_str, "ZERO")
1231
|| !strcasecmp(raw_fb_str, "NONE")) {
1232
raw_fb_str = strdup("map:/dev/zero@640x480x32");
1233
} else if (!strcasecmp(raw_fb_str, "NULLBIG") || !strcasecmp(raw_fb_str, "NONEBIG")) {
1234
raw_fb_str = strdup("map:/dev/zero@1024x768x32");
1236
if (!strcasecmp(raw_fb_str, "RAND")) {
1237
raw_fb_str = strdup("file:/dev/urandom@128x128x16");
1238
} else if (!strcasecmp(raw_fb_str, "RANDBIG")) {
1239
raw_fb_str = strdup("file:/dev/urandom@640x480x16");
1240
} else if (!strcasecmp(raw_fb_str, "RANDHUGE")) {
1241
raw_fb_str = strdup("file:/dev/urandom@1024x768x16");
1243
if (strstr(raw_fb_str, "solid=") == raw_fb_str) {
1244
char *n = raw_fb_str + strlen("solid=");
1245
char tmp[] = "/tmp/solid.XXXXXX";
1247
unsigned int vals[1024], val;
1248
int x, y, fd, w = 1024, h = 768;
1249
if (strstr(n, "0x")) {
1250
if (sscanf(n, "0x%x", &val) != 1) {
1261
for (y = 0; y < h; y++) {
1262
for (x = 0; x < w; x++) {
1265
write(fd, (char *)vals, 4 * w);
1268
fd = open(tmp, O_WRONLY);
1269
unlink_me = strdup(tmp);
1270
sprintf(str, "map:%s@%dx%dx32", tmp, w, h);
1271
raw_fb_str = strdup(str);
1272
} else if (strstr(raw_fb_str, "swirl") == raw_fb_str) {
1273
char tmp[] = "/tmp/solid.XXXXXX";
1275
unsigned int val[1024];
1276
unsigned int c1, c2, c3, c4;
1277
int x, y, fd, w = 1024, h = 768;
1279
for (y = 0; y < h; y++) {
1280
for (x = 0; x < w; x++) {
1282
c2 = ((x+y)*128)/(w+h);
1285
val[x] = (c1 << 24) | (c2 << 16) | (c3 << 8) | (c4 << 0);
1287
write(fd, (char *)val, 4 * w);
1290
fd = open(tmp, O_WRONLY);
1291
unlink_me = strdup(tmp);
1292
sprintf(str, "map:%s@%dx%dx32", tmp, w, h);
1293
raw_fb_str = strdup(str);
1297
if ( (q = strstr(raw_fb_str, "setup:")) == raw_fb_str) {
1299
char line[1024], *t;
1302
q += strlen("setup:");
1304
if (no_external_cmds || !cmd_ok("rawfb-setup")) {
1306
rfbLog("cannot run external commands in -nocmds "
1308
rfbLog(" \"%s\"\n", q);
1309
rfbLog(" exiting.\n");
1312
rfbLog("running command to setup rawfb: %s\n", q);
1314
pipe = popen(q, "r");
1317
rfbLog("popen of setup command failed.\n");
1318
rfbLogPerror("popen");
1322
if (fgets(line, 1024, pipe) == NULL) {
1324
rfbLog("read of setup command failed.\n");
1330
while (*t != '\0') {
1336
rfbLog("setup command returned: %s\n", str);
1339
str = strdup(raw_fb_str);
1341
if (str[0] == '+') {
1342
char *t = strdup(str+1);
1357
raw_fb_bytes_per_line = 0;
1358
/* rawfb_vnc_reflect = 0;*/
1365
if (strstr(str, "Video") == str) {
1366
if (pipeinput_str != NULL) {
1367
free(pipeinput_str);
1369
pipeinput_str = strdup("VID");
1370
initialize_pipeinput();
1374
if (strstr(str, "video") == str || strstr(str, "/dev/video") == str) {
1375
char *str2 = v4l_guess(str, &raw_fb_fd);
1377
rfbLog("v4l_guess failed for: %s\n", str);
1381
rfbLog("v4l_guess returned: %s\n", str);
1382
rawfb_dev_video = 1;
1383
} else if (strstr(str, "dev/video")) {
1384
rawfb_dev_video = 1;
1385
} else if (strstr(str, "console") == str || strstr(str, "fb") == str ||
1386
strstr(str, "/dev/fb") == str) {
1387
char *str2 = console_guess(str, &raw_fb_fd);
1389
rfbLog("console_guess failed for: %s\n", str);
1393
rfbLog("console_guess returned: %s\n", str);
1395
} else if (strstr(str, "vnc:") == str) {
1396
char *str2 = vnc_reflect_guess(str, &raw_fb_addr);
1398
rawfb_vnc_reflect = 1;
1402
rfbLog("vnc_reflector set rawfb str to: %s\n", str);
1403
if (pipeinput_str == NULL) {
1404
pipeinput_str = strdup("VNC");
1406
initialize_pipeinput();
1409
if (closedpy && !view_only && got_noviewonly) {
1410
rfbLog("not closing X DISPLAY under -noviewonly option.\n");
1417
if (! raw_fb_orig_dpy && dpy) {
1418
raw_fb_orig_dpy = strdup(DisplayString(dpy));
1420
#ifndef BOLDLY_CLOSE_DISPLAY
1421
#define BOLDLY_CLOSE_DISPLAY 1
1423
#if BOLDLY_CLOSE_DISPLAY
1426
rfbLog("closing X DISPLAY: %s in rawfb mode.\n",
1427
DisplayString(dpy));
1428
XCloseDisplay_wr(dpy); /* yow! */
1435
* -rawfb shm:163938442@640x480x32:ff/ff00/ff0000+3000
1436
* -rawfb map:/path/to/file@640x480x32:ff/ff00/ff0000
1437
* -rawfb file:/path/to/file@640x480x32:ff/ff00/ff0000
1442
if ((q = strrchr(str, '+')) != NULL) {
1443
if (sscanf(q, "+%d", &raw_fb_offset) == 1) {
1450
if ((q = strrchr(str, ':')) != NULL) {
1451
if (sscanf(q, ":%lx/%lx/%lx", &rm, &gm, &bm) == 3) {
1453
} else if (sscanf(q, ":0x%lx/0x%lx/0x%lx", &rm, &gm, &bm)== 3) {
1455
} else if (sscanf(q, ":%lu/%lu/%lu", &rm, &gm, &bm) == 3) {
1463
if ((q = strrchr(str, '@')) == NULL) {
1465
rfbLog("invalid rawfb str: %s\n", str);
1469
if (strrchr(q, '-')) {
1470
char *q2 = strrchr(q, '-');
1471
raw_fb_bytes_per_line = atoi(q2+1);
1475
if (sscanf(q, "@%dx%dx%d", &w, &h, &b) != 3) {
1477
rfbLog("invalid rawfb str: %s\n", str);
1487
if (rawfb_dev_video) {
1489
rfbLog("enabling -24to32 for 24bpp video\n");
1493
rfbLog("disabling -24to32 for 24bpp video\n");
1501
rfbLog("warning: -24to32 mode and bpp=%d\n", b);
1505
if (strstr(str, "snap:") == str) {
1507
str[0] = 'f'; str[1] = 'i'; str[2] = 'l'; str[3] = 'e';
1510
if (strstr(str, "shm:") != str && strstr(str, "mmap:") != str &&
1511
strstr(str, "map:") != str && strstr(str, "file:") != str) {
1512
/* hmmm, not following directions, see if map: applies */
1514
if (stat(str, &sbuf) == 0) {
1516
int len = strlen("map:") + strlen(str) + 1;
1517
rfbLog("no type prefix: %s\n", raw_fb_str);
1518
rfbLog(" but file exists, so assuming: map:%s\n",
1520
new = (char *) malloc(len);
1521
strcpy(new, "map:");
1528
if (sscanf(str, "shm:%d", &shmid) == 1) {
1530
#if LIBVNCSERVER_HAVE_XSHM
1531
raw_fb_addr = (char *) shmat(shmid, 0, SHM_RDONLY);
1532
if (! raw_fb_addr) {
1534
rfbLog("failed to attach to shm: %d, %s\n", shmid, str);
1535
rfbLogPerror("shmat");
1539
rfbLog("rawfb: shm: %d W: %d H: %d B: %d addr: %p\n",
1540
shmid, w, h, b, raw_fb_addr);
1541
last_mode = RAWFB_SHM;
1544
rfbLog("x11vnc was compiled without shm support.\n");
1545
rfbLogPerror("shmat");
1548
} else if (strstr(str, "map:") == str || strstr(str, "mmap:") == str
1549
|| strstr(str, "file:") == str) {
1550
/* map:/path/... or file:/path */
1551
int fd, do_mmap = 1, size;
1557
q = strchr(str, ':');
1561
if (strstr(q, "macosx:") == q) {
1562
/* mmap:macosx:/dev/null@... */
1563
q += strlen("macosx:");
1569
last_file = strdup(q);
1572
if (fd < 0 && rawfb_dev_video) {
1573
fd = open(q, O_RDWR);
1576
fd = open(q, O_RDONLY);
1580
rfbLog("failed to open file: %s, %s\n", q, str);
1581
rfbLogPerror("open");
1587
size = w*h*24/8 + raw_fb_offset;
1589
size = w*h*b/8 + raw_fb_offset;
1591
if (fstat(fd, &sbuf) == 0) {
1592
if (S_ISREG(sbuf.st_mode)) {
1593
if (0) size = sbuf.st_size;
1595
rfbLog("raw fb is non-regular file: %s\n", q);
1600
raw_fb_addr = macosx_get_fb_addr();
1602
rfbLog("rawfb: macosx fb: %s\n", q);
1603
rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
1604
b, raw_fb_addr, size);
1606
} else if (do_reflect) {
1608
rfbLog("rawfb: vnc fb: %s\n", q);
1609
rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
1610
b, raw_fb_addr, size);
1613
} else if (do_mmap) {
1614
#if LIBVNCSERVER_HAVE_MMAP
1615
raw_fb_addr = mmap(0, size, PROT_READ, MAP_SHARED,
1618
if (raw_fb_addr == MAP_FAILED || raw_fb_addr == NULL) {
1620
rfbLog("failed to mmap file: %s, %s\n", q, str);
1621
rfbLog(" raw_fb_addr: %p\n", raw_fb_addr);
1622
rfbLogPerror("mmap");
1627
rfbLog("rawfb: mmap file: %s\n", q);
1628
rfbLog(" w: %d h: %d b: %d addr: %p sz: %d\n", w, h,
1629
b, raw_fb_addr, size);
1630
last_mode = RAWFB_MMAP;
1632
rfbLog("mmap(2) not supported on system, using"
1633
" slower lseek(2)\n");
1635
last_mode = RAWFB_FILE;
1639
last_mode = RAWFB_FILE;
1641
rfbLog("rawfb: seek file: %s\n", q);
1642
rfbLog(" W: %d H: %d B: %d sz: %d\n", w, h, b, size);
1646
rfbLog("invalid rawfb str: %s\n", str);
1654
if (! raw_fb_image) {
1655
raw_fb_image = &ximage_struct;
1658
initialize_clipshift();
1660
if (raw_fb_bytes_per_line == 0) {
1661
raw_fb_bytes_per_line = dpy_x*b/8;
1664
* Put cases here were we can determine that
1665
* raw_bytes_per_line != dpy_x*b/8
1669
raw_fb_bytes_per_line = macosxCG_CGDisplayBytesPerRow();
1674
raw_fb_image->bytes_per_line = dpy_x * b/8;
1675
raw_fb = (char *) malloc(dpy_y * dpy_x * b/8);
1676
raw_fb_image->data = raw_fb;
1677
raw_fb_image->format = ZPixmap;
1678
raw_fb_image->width = dpy_x;
1679
raw_fb_image->height = dpy_y;
1680
raw_fb_image->bits_per_pixel = b;
1681
raw_fb_image->bitmap_unit = -1;
1684
if (use_snapfb && (raw_fb_seek || raw_fb_mmap)) {
1689
if (b_use == 32 && xform24to32) {
1691
* The actual framebuffer (e.g. mapped addr) and
1692
* snap fb must be the same bpp. E.g. both 24bpp.
1693
* Reading FROM snap to utility image will be
1694
* transformed 24->32 in copy_raw_fb_24_to_32.
1696
* addr -> snap -> (scanline, fullscreen, ...)
1699
raw_fb_bytes_per_line = dpy_x * b_use/8;
1701
snap_fb = (char *) malloc(dpy_y * dpy_x * b_use/8);
1702
snap = &ximage_struct_snap;
1703
snap->data = snap_fb;
1704
snap->format = ZPixmap;
1705
snap->width = dpy_x;
1706
snap->height = dpy_y;
1707
snap->bits_per_pixel = b_use;
1708
snap->bytes_per_line = dpy_x * b_use/8;
1709
snap->bitmap_unit = -1;
1712
if (rm == 0 && gm == 0 && bm == 0) {
1713
/* guess masks... */
1714
if (b == 24 || b == 32) {
1718
} else if (b == 16) {
1722
} else if (b == 8) {
1728
/* we can fake -flipbyteorder to some degree... */
1729
if (flip_byte_order) {
1730
if (b == 24 || b == 32) {
1734
} else if (b == 16) {
1735
unsigned short s1, s2;
1736
s1 = (unsigned short) rm;
1737
s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
1738
rm = (unsigned long) s2;
1739
s1 = (unsigned short) gm;
1740
s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
1741
gm = (unsigned long) s2;
1742
s1 = (unsigned short) bm;
1743
s2 = ((0xff & s1) << 8) | ((0xff00 & s1) >> 8);
1744
bm = (unsigned long) s2;
1749
raw_fb_image->red_mask = rm;
1750
raw_fb_image->green_mask = gm;
1751
raw_fb_image->blue_mask = bm;
1753
raw_fb_image->depth = 0;
1755
for (i=0; i<32; i++) {
1757
raw_fb_image->depth++;
1760
raw_fb_image->depth++;
1763
raw_fb_image->depth++;
1767
if (! raw_fb_image->depth) {
1768
raw_fb_image->depth = (b == 32) ? 24 : b;
1771
depth = raw_fb_image->depth;
1773
if (raw_fb_image->depth == 15) {
1774
/* unresolved bug with RGB555... */
1779
memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line);
1780
} else if (raw_fb_addr && ! xform24to32) {
1781
memcpy(raw_fb, raw_fb_addr + raw_fb_offset, dpy_y * raw_fb_image->bytes_per_line);
1783
memset(raw_fb, 0xff, dpy_y * raw_fb_image->bytes_per_line);
1789
rfbLog("rawfb: raw_fb %p\n", raw_fb);
1790
rfbLog(" format %d\n", raw_fb_image->format);
1791
rfbLog(" width %d\n", raw_fb_image->width);
1792
rfbLog(" height %d\n", raw_fb_image->height);
1793
rfbLog(" bpp %d\n", raw_fb_image->bits_per_pixel);
1794
rfbLog(" depth %d\n", raw_fb_image->depth);
1795
rfbLog(" bpl %d\n", raw_fb_image->bytes_per_line);
1796
if (use_snapfb && snap_fb) {
1797
rfbLog(" snap_fb %p\n", snap_fb);
1803
return raw_fb_image;
1806
static void initialize_clipshift(void) {
1808
cdpy_x = cdpy_y = coff_x = coff_y = 0;
1810
int w, h, x, y, bad = 0;
1811
if (parse_geom(clip_str, &w, &h, &x, &y, wdpy_x, wdpy_y)) {
1818
if (x + w > wdpy_x) {
1821
if (y + h > wdpy_y) {
1824
if (w <= 0 || h <= 0) {
1831
rfbLog("skipping invalid -clip WxH+X+Y: %s\n",
1834
/* OK, change geom behind everyone's back... */
1848
static int wait_until_mapped(Window win) {
1853
int ms = 50, waittime = 30;
1854
time_t start = time(NULL);
1855
XWindowAttributes attr;
1858
if (! valid_window(win, NULL, 0)) {
1859
if (time(NULL) > start + waittime) {
1865
if (dpy && ! XGetWindowAttributes(dpy, win, &attr)) {
1868
if (attr.map_state == IsViewable) {
1878
* initialize a fb for the X display
1880
XImage *initialize_xdisplay_fb(void) {
1883
return initialize_raw_fb(0);
1888
char *vis_str = visual_str;
1889
int try = 0, subwin_tries = 3;
1890
XErrorHandler old_handler = NULL;
1894
return initialize_raw_fb(0);
1899
if (subwin_wait_mapped) {
1900
wait_until_mapped(subwin);
1902
if (!valid_window((Window) subwin, NULL, 0)) {
1904
rfbLog("invalid sub-window: 0x%lx\n", subwin);
1912
* ideally we'd like to not have to cook up the
1913
* visual variables but rather let it all come out
1914
* of XReadScreen(), however there is no way to get
1915
* a default visual out of it, so we pretend -visual
1916
* TrueColor:NN was supplied with NN usually 24.
1919
Window twin = subwin ? subwin : rootwin;
1922
xi = xreadscreen(dpy, twin, 0, 0, 8, 8, False);
1923
sprintf(str, "TrueColor:%d", xi->depth);
1924
if (xi->depth != 24 && ! quiet) {
1925
rfbLog("warning: overlay image has depth %d "
1926
"instead of 24.\n", xi->depth);
1929
if (visual_str != NULL && ! quiet) {
1930
rfbLog("warning: replacing '-visual %s' by '%s' "
1931
"for use with -overlay\n", visual_str, str);
1933
vis_str = strdup(str);
1937
if (DefaultDepth(dpy, scr) == 24) {
1938
vis_str = strdup("TrueColor:32");
1939
rfbLog("initialize_xdisplay_fb: vis_str set to: %s ",
1941
visual_id = (VisualID) 0;
1943
set_visual_str_to_something = 1;
1947
if (vis_str != NULL) {
1948
set_visual(vis_str);
1949
if (vis_str != visual_str) {
1953
if (0) fprintf(stderr, "vis_str %s\n", vis_str ? vis_str : "notset");
1955
/* set up parameters for subwin or non-subwin cases: */
1960
dpy_x = wdpy_x = DisplayWidth(dpy, scr);
1961
dpy_y = wdpy_y = DisplayHeight(dpy, scr);
1964
/* this may be overridden via visual_id below */
1965
default_visual = DefaultVisual(dpy, scr);
1968
XWindowAttributes attr;
1970
window = (Window) subwin;
1971
if (! XGetWindowAttributes(dpy, window, &attr)) {
1973
rfbLog("invalid window: 0x%lx\n", window);
1977
dpy_x = wdpy_x = attr.width;
1978
dpy_y = wdpy_y = attr.height;
1980
subwin_bs = attr.backing_store;
1982
/* this may be overridden via visual_id below */
1983
default_visual = attr.visual;
1990
initialize_clipshift();
1992
/* initialize depth to reasonable value, visual_id may override */
1993
depth = DefaultDepth(dpy, scr);
1995
if (0) fprintf(stderr, "DefaultDepth: %d visial_id: %d\n", depth, (int) visual_id);
1999
XVisualInfo vinfo_tmpl, *vinfo;
2002
* we are in here from -visual or -overlay options
2003
* visual_id and visual_depth were set in set_visual().
2006
vinfo_tmpl.visualid = visual_id;
2007
vinfo = XGetVisualInfo(dpy, VisualIDMask, &vinfo_tmpl, &n);
2008
if (vinfo == NULL || n == 0) {
2010
rfbLog("could not match visual_id: 0x%x\n",
2015
default_visual = vinfo->visual;
2016
depth = vinfo->depth;
2018
/* force it from -visual MooColor:NN */
2019
depth = visual_depth;
2022
fprintf(stderr, " initialize_xdisplay_fb()\n");
2023
fprintf(stderr, " Visual*: %p\n",
2024
(void *) vinfo->visual);
2025
fprintf(stderr, " visualid: 0x%x\n",
2026
(int) vinfo->visualid);
2027
fprintf(stderr, " screen: %d\n", vinfo->screen);
2028
fprintf(stderr, " depth: %d\n", vinfo->depth);
2029
fprintf(stderr, " class: %d\n", vinfo->class);
2030
fprintf(stderr, " red_mask: 0x%08lx %s\n",
2031
vinfo->red_mask, bitprint(vinfo->red_mask, 32));
2032
fprintf(stderr, " green_mask: 0x%08lx %s\n",
2033
vinfo->green_mask, bitprint(vinfo->green_mask, 32));
2034
fprintf(stderr, " blue_mask: 0x%08lx %s\n",
2035
vinfo->blue_mask, bitprint(vinfo->blue_mask, 32));
2036
fprintf(stderr, " cmap_size: %d\n",
2037
vinfo->colormap_size);
2038
fprintf(stderr, " bits b/rgb: %d\n",
2039
vinfo->bits_per_rgb);
2040
fprintf(stderr, "\n");
2046
rfbLog("Default visual ID: 0x%x\n",
2047
(int) XVisualIDFromVisual(default_visual));
2053
int subwin_x, subwin_y;
2054
int disp_x = DisplayWidth(dpy, scr);
2055
int disp_y = DisplayHeight(dpy, scr);
2057
/* subwins can be a dicey if they are changing size... */
2059
old_handler = XSetErrorHandler(trap_xerror);
2060
XTranslateCoordinates(dpy, window, rootwin, 0, 0, &subwin_x,
2063
if (subwin_x + wdpy_x > disp_x) {
2065
subwin_x = disp_x - wdpy_x - 3;
2067
if (subwin_y + wdpy_y > disp_y) {
2069
subwin_y = disp_y - wdpy_y - 3;
2081
XMoveWindow(dpy, window, subwin_x, subwin_y);
2083
XMapRaised(dpy, window);
2084
XRaiseWindow(dpy, window);
2091
* For -nofb we do not allocate the framebuffer, so we
2092
* can save a few MB of memory.
2094
fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap,
2095
0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0);
2097
} else if (visual_id) {
2099
* we need to call XCreateImage to supply the visual
2101
fb = XCreateImage_wr(dpy, default_visual, depth, ZPixmap,
2102
0, NULL, dpy_x, dpy_y, BitmapPad(dpy), 0);
2103
fb->data = (char *) malloc(fb->bytes_per_line * fb->height);
2106
fb = XGetImage_wr(dpy, window, 0, 0, dpy_x, dpy_y, AllPlanes,
2109
rfbLog("Read initial data from X display into"
2115
XSetErrorHandler(old_handler);
2116
if (trapped_xerror) {
2117
rfbLog("trapped GetImage at SUBWIN creation.\n");
2118
if (try < subwin_tries) {
2120
if (!get_window_size(window, &wdpy_x, &wdpy_y)) {
2122
rfbLog("could not get size of subwin "
2132
} else if (! fb && try == 1) {
2138
initialize_snap_fb();
2142
if (fb->bits_per_pixel == 24 && ! quiet) {
2143
rfbLog("warning: 24 bpp may have poor performance.\n");
2149
void parse_scale_string(char *str, double *factor, int *scaling, int *blend,
2150
int *nomult4, int *pad, int *interpolate, int *numer, int *denom) {
2162
*numer = 0, *denom = 0;
2164
if (str == NULL || str[0] == '\0') {
2169
if ( (p = strchr(tstr, ':')) != NULL) {
2171
if (strstr(p+1, "nb") != NULL) {
2174
if (strstr(p+1, "fb") != NULL) {
2177
if (strstr(p+1, "n4") != NULL) {
2180
if (strstr(p+1, "in") != NULL) {
2183
if (strstr(p+1, "pad") != NULL) {
2186
if (strstr(p+1, "nocr") != NULL) {
2188
scaling_copyrect = 0;
2189
} else if (strstr(p+1, "cr") != NULL) {
2191
scaling_copyrect = 1;
2195
if (strchr(tstr, '.') != NULL) {
2196
double test, diff, eps = 1.0e-7;
2197
if (sscanf(tstr, "%lf", &f) != 1) {
2199
rfbLog("invalid -scale arg: %s\n", tstr);
2202
*factor = (double) f;
2203
/* look for common fractions from small ints: */
2204
for (n=2; n<=10; n++) {
2205
for (m=1; m<n; m++) {
2206
test = ((double) m)/ n;
2207
diff = *factor - test;
2208
if (-eps < diff && diff < eps) {
2219
if (*factor < 0.01) {
2221
rfbLog("-scale factor too small: %f\n", scale_fac);
2225
if (sscanf(tstr, "%d/%d", &m, &n) != 2) {
2226
if (sscanf(tstr, "%d", &m) != 1) {
2228
rfbLog("invalid -scale arg: %s\n", tstr);
2231
/* e.g. -scale 1 or -scale 2 */
2235
if (n <= 0 || m <=0) {
2237
rfbLog("invalid -scale arg: %s\n", tstr);
2240
*factor = ((double) m)/ n;
2241
if (*factor < 0.01) {
2243
rfbLog("-scale factor too small: %f\n", *factor);
2249
if (*factor == 1.0) {
2251
rfbLog("scaling disabled for factor %f\n", *factor);
2259
int parse_rotate_string(char *str, int *mode) {
2260
int m = ROTATE_NONE;
2261
if (str == NULL || !strcmp(str, "") || !strcmp(str, "0")) {
2263
} else if (!strcmp(str, "x")) {
2265
} else if (!strcmp(str, "y")) {
2267
} else if (!strcmp(str, "xy") || !strcmp(str, "yx") ||
2268
!strcmp(str,"+180") || !strcmp(str,"-180") || !strcmp(str,"180")) {
2270
} else if (!strcmp(str, "+90") || !strcmp(str, "90")) {
2272
} else if (!strcmp(str, "+90x") || !strcmp(str, "90x")) {
2274
} else if (!strcmp(str, "+90y") || !strcmp(str, "90y")) {
2276
} else if (!strcmp(str, "-90") || !strcmp(str, "270") ||
2277
!strcmp(str, "+270")) {
2280
rfbLog("invalid -rotate mode: %s\n", str);
2288
int scale_round(int len, double fac) {
2289
double eps = 0.000001;
2291
len = (int) (len * fac + eps);
2298
static void setup_scaling(int *width_in, int *height_in) {
2299
int width = *width_in;
2300
int height = *height_in;
2302
parse_scale_string(scale_str, &scale_fac, &scaling, &scaling_blend,
2303
&scaling_nomult4, &scaling_pad, &scaling_interpolate,
2304
&scale_numer, &scale_denom);
2307
width = scale_round(width, scale_fac);
2308
height = scale_round(height, scale_fac);
2309
if (scale_denom && scaling_pad) {
2310
/* it is not clear this padding is useful anymore */
2311
rfbLog("width %% denom: %d %% %d = %d\n", width,
2312
scale_denom, width % scale_denom);
2313
rfbLog("height %% denom: %d %% %d = %d\n", height,
2314
scale_denom, height % scale_denom);
2315
if (width % scale_denom != 0) {
2317
w += scale_denom - (w % scale_denom);
2318
if (!scaling_nomult4 && w % 4 != 0) {
2319
/* need to make mult of 4 as well */
2321
while (w % 4 != 0 && c++ <= 5) {
2326
rfbLog("padded width to: %d (mult of %d%s\n",
2327
width, scale_denom, !scaling_nomult4 ?
2330
if (height % scale_denom != 0) {
2331
height += scale_denom - (height % scale_denom);
2332
rfbLog("padded height to: %d (mult of %d)\n",
2333
height, scale_denom);
2336
if (!scaling_nomult4 && width % 4 != 0 && width > 2) {
2337
/* reset width to be multiple of 4 */
2339
if ((width+1) % 4 == 0) {
2341
} else if ((width-1) % 4 == 0) {
2343
} else if ((width+2) % 4 == 0) {
2346
rfbLog("reset scaled width %d -> %d to be a multiple of"
2347
" 4 (to\n", width0, width);
2348
rfbLog("make vncviewers happy). use -scale m/n:n4 to "
2355
*height_in = height;
2359
static void setup_rotating(void) {
2360
char *rs = rotating_str;
2362
rotating_cursors = 1;
2363
if (rs && strstr(rs, "nc:") == rs) {
2364
rs += strlen("nc:");
2365
rotating_cursors = 0;
2368
rotating = parse_rotate_string(rs, NULL);
2370
rotating_cursors = 0;
2373
if (rotating == ROTATE_90 || rotating == ROTATE_90X ||
2374
rotating == ROTATE_90Y || rotating == ROTATE_270) {
2381
static rfbBool set_xlate_wrapper(rfbClientPtr cl) {
2382
static int first = 1;
2385
} else if (ncache) {
2386
int save = ncache_xrootpmap;
2387
rfbLog("set_xlate_wrapper: clearing -ncache for new pixel format.\n");
2388
ncache_xrootpmap = 0;
2390
ncache_xrootpmap = save;
2392
return rfbSetTranslateFunction(cl);
2396
* initialize the rfb framebuffer/screen
2398
void initialize_screen(int *argc, char **argv, XImage *fb) {
2400
int width = fb->width;
2401
int height = fb->height;
2402
int create_screen = screen ? 0 : 1;
2404
int fb_bpp, fb_Bpl, fb_depth;
2406
bpp = fb->bits_per_pixel;
2408
fb_bpp = (int) fb->bits_per_pixel;
2409
fb_Bpl = (int) fb->bytes_per_line;
2410
fb_depth = (int) fb->depth;
2412
rfbLog("initialize_screen: fb_depth/fb_bpp/fb_Bpl %d/%d/%d\n", fb_depth,
2415
main_bytes_per_line = fb->bytes_per_line;
2419
if (!quiet) rfbLog("disabling -8to24 mode"
2420
" in raw_fb mode.\n");
2422
} else if (depth == 24) {
2424
if (!quiet) rfbLog("disabling -8to24 mode:"
2425
" bpp != 32 with depth == 24\n");
2428
} else if (depth == 8) {
2429
/* need to cook up the screen fb to be depth 24 */
2433
if (!quiet) rfbLog("disabling -8to24 mode:"
2434
" default depth not 24 or 8\n");
2439
setup_scaling(&width, &height);
2442
rfbLog("scaling screen: %dx%d -> %dx%d scale_fac=%.5f\n",
2443
fb->width, fb->height, scaled_x, scaled_y, scale_fac);
2445
rfb_bytes_per_line = (main_bytes_per_line / fb->width) * width;
2447
rfb_bytes_per_line = main_bytes_per_line;
2453
if (! rotating_same) {
2454
int t, b = main_bytes_per_line / fb->width;
2456
rot_bytes_per_line = b * height;
2458
rot_bytes_per_line = b * fb->height;
2461
width = height; /* The big swap... */
2464
rot_bytes_per_line = rfb_bytes_per_line;
2469
if (ncache > 0 && !nofb) {
2471
if (! raw_fb_str || macosx_console) {
2477
int sz = fb->height * fb->bytes_per_line;
2480
if (ncache_xrootpmap) {
2484
new_fb = (char *) calloc((size_t) (sz * ns), 1);
2486
memcpy(new_fb, fb->data, sz);
2497
if (cmap8to24 && depth == 8) {
2498
rfb_bytes_per_line *= 4;
2499
rot_bytes_per_line *= 4;
2503
* These are just hints wrt pixel format just to let
2504
* rfbGetScreen/rfbNewFramebuffer proceed with reasonable
2505
* defaults. We manually set them in painful detail below.
2507
bits_per_color = guess_bits_per_color(fb_bpp);
2509
/* n.b. samplesPerPixel (set = 1 here) seems to be unused. */
2510
if (create_screen) {
2513
} else if (use_stunnel) {
2514
setup_stunnel(0, argc, argv);
2516
screen = rfbGetScreen(argc, argv, width, height,
2517
bits_per_color, 1, fb_bpp/8);
2518
if (screen && http_dir) {
2519
http_connections(1);
2522
/* set set frameBuffer member below. */
2523
rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n",
2524
screen, NULL, width, height, bits_per_color, 1, fb_bpp/8);
2526
/* these are probably overwritten, but just to be safe: */
2527
screen->bitsPerPixel = fb_bpp;
2528
screen->depth = fb_depth;
2530
rfbNewFramebuffer(screen, NULL, width, height,
2531
bits_per_color, 1, (int) fb_bpp/8);
2537
rfbLog("failed to create rfb screen.\n");
2538
for (i=0; i< *argc; i++) {
2539
rfbLog("\t[%d] %s\n", i, argv[i]);
2544
if (create_screen && *argc != 1) {
2547
rfbLog("*** unrecognized option(s) ***\n");
2548
for (i=1; i< *argc; i++) {
2549
rfbLog("\t[%d] %s\n", i, argv[i]);
2551
rfbLog("For a list of options run: x11vnc -opts\n");
2552
rfbLog("or for the full help: x11vnc -help\n");
2554
rfbLog("Here is a list of removed or obsolete"
2557
rfbLog("removed: -hints, -nohints\n");
2558
rfbLog("removed: -cursorposall\n");
2559
rfbLog("removed: -nofilexfer, now the default.\n");
2561
rfbLog("renamed: -old_copytile, use -onetile\n");
2562
rfbLog("renamed: -mouse, use -cursor\n");
2563
rfbLog("renamed: -mouseX, use -cursor X\n");
2564
rfbLog("renamed: -X, use -cursor X\n");
2565
rfbLog("renamed: -nomouse, use -nocursor\n");
2566
rfbLog("renamed: -old_pointer, use -pointer_mode 1\n");
2571
/* set up format from scratch: */
2572
if (rotating && ! rotating_same) {
2573
screen->paddedWidthInBytes = rot_bytes_per_line;
2575
screen->paddedWidthInBytes = rfb_bytes_per_line;
2577
screen->serverFormat.bitsPerPixel = fb_bpp;
2578
screen->serverFormat.depth = fb_depth;
2579
screen->serverFormat.trueColour = TRUE;
2581
screen->serverFormat.redShift = 0;
2582
screen->serverFormat.greenShift = 0;
2583
screen->serverFormat.blueShift = 0;
2584
screen->serverFormat.redMax = 0;
2585
screen->serverFormat.greenMax = 0;
2586
screen->serverFormat.blueMax = 0;
2588
/* these main_* formats are used generally. */
2590
main_green_shift = 0;
2591
main_blue_shift = 0;
2595
main_red_mask = fb->red_mask;
2596
main_green_mask = fb->green_mask;
2597
main_blue_mask = fb->blue_mask;
2599
have_masks = ((fb->red_mask|fb->green_mask|fb->blue_mask) != 0);
2600
if (force_indexed_color) {
2604
if (cmap8to24 && depth == 8 && dpy) {
2607
vinfo.green_mask = 0;
2608
vinfo.blue_mask = 0;
2609
/* more cooking up... */
2611
/* need to fetch TrueColor visual */
2615
&& XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinfo)
2618
main_red_mask = vinfo.red_mask;
2619
main_green_mask = vinfo.green_mask;
2620
main_blue_mask = vinfo.blue_mask;
2621
} else if (fb->byte_order == LSBFirst) {
2622
main_red_mask = 0x00ff0000;
2623
main_green_mask = 0x0000ff00;
2624
main_blue_mask = 0x000000ff;
2626
main_red_mask = 0x000000ff;
2627
main_green_mask = 0x0000ff00;
2628
main_blue_mask = 0x00ff0000;
2633
if (raw_fb_str && raw_fb_pixfmt) {
2634
char *fmt = strdup(raw_fb_pixfmt);
2636
if (strstr(fmt, "GREY")) {
2637
set_greyscale_colormap();
2638
} else if (strstr(fmt, "HI240")) {
2639
set_hi240_colormap();
2646
if (! have_masks && screen->serverFormat.bitsPerPixel == 8
2647
&& dpy && CellsOfScreen(ScreenOfDisplay(dpy, scr))) {
2651
rfbLog("X display %s is 8bpp indexed color\n",
2652
DisplayString(dpy));
2653
if (! flash_cmap && ! overlay) {
2655
rfbLog("In 8bpp PseudoColor mode if you "
2656
"experience color\n");
2657
rfbLog("problems you may want to enable "
2659
rfbLog("changing colormap by using the "
2660
"-flashcmap option.\n");
2664
screen->serverFormat.trueColour = FALSE;
2670
* general case, we call it truecolor, but could be direct
2671
* color, static color, etc....
2676
rfbLog("Raw fb at addr %p is %dbpp depth=%d "
2677
"true color\n", raw_fb_addr,
2681
} else if (have_masks == 2) {
2683
rfbLog("X display %s is %dbpp depth=%d indexed "
2684
"color (-8to24 mode)\n", DisplayString(dpy),
2685
fb->bits_per_pixel, fb->depth);
2688
rfbLog("X display %s is %dbpp depth=%d true "
2689
"color\n", DisplayString(dpy),
2696
/* convert masks to bit shifts and max # colors */
2697
if (main_red_mask) {
2698
while (! (main_red_mask
2699
& (1 << screen->serverFormat.redShift))) {
2700
screen->serverFormat.redShift++;
2703
if (main_green_mask) {
2704
while (! (main_green_mask
2705
& (1 << screen->serverFormat.greenShift))) {
2706
screen->serverFormat.greenShift++;
2709
if (main_blue_mask) {
2710
while (! (main_blue_mask
2711
& (1 << screen->serverFormat.blueShift))) {
2712
screen->serverFormat.blueShift++;
2715
screen->serverFormat.redMax
2716
= main_red_mask >> screen->serverFormat.redShift;
2717
screen->serverFormat.greenMax
2718
= main_green_mask >> screen->serverFormat.greenShift;
2719
screen->serverFormat.blueMax
2720
= main_blue_mask >> screen->serverFormat.blueShift;
2722
main_red_max = screen->serverFormat.redMax;
2723
main_green_max = screen->serverFormat.greenMax;
2724
main_blue_max = screen->serverFormat.blueMax;
2726
main_red_shift = screen->serverFormat.redShift;
2727
main_green_shift = screen->serverFormat.greenShift;
2728
main_blue_shift = screen->serverFormat.blueShift;
2731
#if !SMALL_FOOTPRINT
2733
fprintf(stderr, "\n");
2734
fprintf(stderr, "FrameBuffer Info:\n");
2735
fprintf(stderr, " width: %d\n", fb->width);
2736
fprintf(stderr, " height: %d\n", fb->height);
2737
fprintf(stderr, " scaled_width: %d\n", width);
2738
fprintf(stderr, " scaled_height: %d\n", height);
2739
fprintf(stderr, " indexed_color: %d\n", indexed_color);
2740
fprintf(stderr, " bits_per_pixel: %d\n", fb->bits_per_pixel);
2741
fprintf(stderr, " depth: %d\n", fb->depth);
2742
fprintf(stderr, " red_mask: 0x%08lx %s\n", fb->red_mask,
2743
bitprint(fb->red_mask, 32));
2744
fprintf(stderr, " green_mask: 0x%08lx %s\n", fb->green_mask,
2745
bitprint(fb->green_mask, 32));
2746
fprintf(stderr, " blue_mask: 0x%08lx %s\n", fb->blue_mask,
2747
bitprint(fb->blue_mask, 32));
2749
fprintf(stderr, " 8to24 info:\n");
2750
fprintf(stderr, " fb_bpp: %d\n", fb_bpp);
2751
fprintf(stderr, " fb_depth: %d\n", fb_depth);
2752
fprintf(stderr, " red_mask: 0x%08lx %s\n", main_red_mask,
2753
bitprint(main_red_mask, 32));
2754
fprintf(stderr, " green_mask: 0x%08lx %s\n", main_green_mask,
2755
bitprint(main_green_mask, 32));
2756
fprintf(stderr, " blue_mask: 0x%08lx %s\n", main_blue_mask,
2757
bitprint(main_blue_mask, 32));
2759
fprintf(stderr, " red: max: %3d shift: %2d\n",
2760
main_red_max, main_red_shift);
2761
fprintf(stderr, " green: max: %3d shift: %2d\n",
2762
main_green_max, main_green_shift);
2763
fprintf(stderr, " blue: max: %3d shift: %2d\n",
2764
main_blue_max, main_blue_shift);
2765
fprintf(stderr, " mainfb_bytes_per_line: %d\n",
2766
main_bytes_per_line);
2767
fprintf(stderr, " rfb_fb_bytes_per_line: %d\n",
2768
rfb_bytes_per_line);
2769
fprintf(stderr, " rot_fb_bytes_per_line: %d\n",
2770
rot_bytes_per_line);
2771
fprintf(stderr, " raw_fb_bytes_per_line: %d\n",
2772
raw_fb_bytes_per_line);
2773
switch(fb->format) {
2775
fprintf(stderr, " format: XYBitmap\n"); break;
2777
fprintf(stderr, " format: XYPixmap\n"); break;
2779
fprintf(stderr, " format: ZPixmap\n"); break;
2781
fprintf(stderr, " format: %d\n", fb->format); break;
2783
switch(fb->byte_order) {
2785
fprintf(stderr, " byte_order: LSBFirst\n"); break;
2787
fprintf(stderr, " byte_order: MSBFirst\n"); break;
2789
fprintf(stderr, " byte_order: %d\n", fb->byte_order);
2792
fprintf(stderr, " bitmap_pad: %d\n", fb->bitmap_pad);
2793
fprintf(stderr, " bitmap_unit: %d\n", fb->bitmap_unit);
2794
switch(fb->bitmap_bit_order) {
2796
fprintf(stderr, " bitmap_bit_order: LSBFirst\n"); break;
2798
fprintf(stderr, " bitmap_bit_order: MSBFirst\n"); break;
2800
fprintf(stderr, " bitmap_bit_order: %d\n",
2801
fb->bitmap_bit_order); break;
2804
if (overlay && ! quiet) {
2806
rfbLog("Overlay mode enabled: If you experience color\n");
2807
rfbLog("problems when popup menus are on the screen, try\n");
2808
rfbLog("disabling SaveUnders in your X server, one way is\n");
2809
rfbLog("to start the X server with the '-su' option, e.g.:\n");
2810
rfbLog("Xsun -su ... see Xserver(1), xinit(1) for more info.\n");
2814
/* nofb is for pointer/keyboard only handling. */
2818
cmap8to24_fb = NULL;
2820
screen->displayHook = nofb_hook;
2824
cmap8to24_fb = NULL;
2828
int n = main_bytes_per_line * fb->height;
2832
cmap8to24_fb = (char *) malloc(n);
2833
memset(cmap8to24_fb, 0, n);
2837
int n = rot_bytes_per_line * height;
2838
rot_fb = (char *) malloc(n);
2839
memset(rot_fb, 0, n);
2843
int n = rfb_bytes_per_line * height;
2845
if (rotating && ! rotating_same) {
2846
n = rot_bytes_per_line * height;
2849
rfb_fb = (char *) malloc(n);
2850
memset(rfb_fb, 0, n);
2852
} else if (cmap8to24) {
2853
rfb_fb = cmap8to24_fb;
2859
screen->frameBuffer = rot_fb;
2861
screen->frameBuffer = rfb_fb;
2864
fprintf(stderr, " rfb_fb: %p\n", rfb_fb);
2865
fprintf(stderr, " main_fb: %p\n", main_fb);
2866
fprintf(stderr, " 8to24_fb: %p\n", cmap8to24_fb);
2867
fprintf(stderr, " rot_fb: %p\n", rot_fb);
2868
fprintf(stderr, " snap_fb: %p\n", snap_fb);
2869
fprintf(stderr, " raw_fb: %p\n", raw_fb);
2870
fprintf(stderr, " fake_fb: %p\n", fake_fb);
2871
fprintf(stderr, "\n");
2874
/* may need, bpp, main_red_max, etc. */
2876
parse_scroll_copyrect();
2878
setup_cursors_and_push();
2880
if (scaling || rotating || cmap8to24) {
2881
mark_rect_as_modified(0, 0, dpy_x, dpy_y, 0);
2884
if (! create_screen) {
2885
rfbClientIteratorPtr iter;
2889
* since bits_per_color above may have been approximate,
2890
* try to reset the individual translation tables...
2891
* we do not seem to need this with rfbGetScreen()...
2893
if (!quiet) rfbLog("calling setTranslateFunction()...\n");
2894
iter = rfbGetClientIterator(screen);
2895
while ((cl = rfbClientIteratorNext(iter)) != NULL) {
2896
screen->setTranslateFunction(cl);
2898
rfbReleaseClientIterator(iter);
2899
if (!quiet) rfbLog(" done.\n");
2902
/* done for framebuffer change case */
2907
* the rest is screen server initialization, etc, only needed
2908
* at screen creation time.
2911
/* event callbacks: */
2912
screen->newClientHook = new_client;
2913
screen->kbdAddEvent = keyboard;
2914
screen->ptrAddEvent = pointer;
2915
screen->setXCutText = xcut_receive;
2916
screen->setTranslateFunction = set_xlate_wrapper;
2918
screen->kbdReleaseAllKeys = kbd_release_all_keys;
2919
screen->setSingleWindow = set_single_window;
2920
screen->setServerInput = set_server_input;
2921
screen->setTextChat = set_text_chat;
2922
screen->getFileTransferPermission = get_file_transfer_permitted;
2924
/* called from inetd, we need to treat stdio as our socket */
2925
if (inetd && use_openssl) {
2926
/* accept_openssl() called later */
2932
rfbErr("dup(0) = %d failed.\n", fd);
2933
rfbLogPerror("dup");
2938
/* we keep stderr for logging */
2939
screen->inetdSock = fd;
2942
} else if (! got_rfbport && auto_port > 0) {
2943
int lport = find_free_port(auto_port, auto_port+200);
2944
screen->autoPort = FALSE;
2945
screen->port = lport;
2946
} else if (! got_rfbport) {
2947
screen->autoPort = TRUE;
2948
} else if (got_rfbport && got_rfbport_val == 0) {
2949
screen->autoPort = FALSE;
2953
if (! got_nevershared && ! got_alwaysshared) {
2955
screen->alwaysShared = TRUE;
2957
screen->neverShared = TRUE;
2959
screen->dontDisconnect = TRUE;
2961
if (! got_deferupdate) {
2962
screen->deferUpdateTime = defer_update;
2965
rfbInitServer(screen);
2969
if (https_port_num >= 0) {
2979
avahi_initialise(); \
2980
avahi_advertise(vnc_desktop_name, host, lport); \
2981
usleep(1000*1000); \
2984
void announce(int lport, int ssl, char *iface) {
2986
char *host = this_host();
2990
tvdt = "The VNC desktop is: ";
2992
tvdt = "The SSL VNC desktop is: ";
2995
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
2999
/* note that vncviewer special cases 5900-5999 */
3002
; /* should not occur (port) */
3004
if (lport >= 5900) {
3005
snprintf(vnc_desktop_name, sz, "%s:%d",
3006
host, lport - 5900);
3008
fprintf(stderr, "\n%s %s\n", tvdt,
3011
snprintf(vnc_desktop_name, sz, "%s:%d",
3014
fprintf(stderr, "\n%s %s\n", tvdt,
3017
} else if (lport >= 5900) {
3018
snprintf(vnc_desktop_name, sz, "%s:%d",
3019
host, lport - 5900);
3021
fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name);
3022
if (lport >= 6000) {
3023
rfbLog("possible aliases: %s:%d, "
3024
"%s::%d\n", host, lport,
3028
snprintf(vnc_desktop_name, sz, "%s:%d",
3031
fprintf(stderr, "\n%s %s\n", tvdt, vnc_desktop_name);
3032
rfbLog("possible alias: %s::%d\n",
3038
static void announce_http(int lport, int ssl, char *iface) {
3040
char *host = this_host();
3044
jvu = "Java SSL viewer URL: https";
3045
} else if (ssl == 2) {
3046
jvu = "Java SSL viewer URL: http";
3048
jvu = "Java viewer URL: http";
3051
if (iface != NULL && *iface != '\0' && strcmp(iface, "any")) {
3056
fprintf(stderr, "%s://%s:%d/\n", jvu, host, lport);
3061
void set_vnc_desktop_name(void) {
3062
sprintf(vnc_desktop_name, "unknown");
3064
sprintf(vnc_desktop_name, "%s/inetd-no-further-clients",
3070
if (screen->httpListenSock > -1 && screen->httpPort) {
3072
rfbLog("The URLs printed out below ('Java ... viewer URL') can\n");
3073
rfbLog("be used for Java enabled Web browser connections.\n");
3074
if (use_openssl || stunnel_port) {
3075
rfbLog("Here are some additional possibilities:\n");
3077
rfbLog("https://host:port/proxy.vnc (MUST be used if Web Proxy used)\n");
3079
rfbLog("https://host:port/ultra.vnc (Use UltraVNC Java Viewer)\n");
3080
rfbLog("https://host:port/ultraproxy.vnc (Web Proxy with UltraVNC)\n");
3081
rfbLog("https://host:port/ultrasigned.vnc (Signed UltraVNC Filexfer)\n");
3083
rfbLog("Where you replace \"host:port\" with that printed below, or\n");
3084
rfbLog("whatever is needed to reach the host e.g. Internet IP number\n");
3091
announce(screen->port, 1, listen_str);
3093
announce(screen->port, 0, listen_str);
3096
announce(stunnel_port, 1, NULL);
3098
if (screen->httpListenSock > -1 && screen->httpPort) {
3100
announce_http(screen->port, 1, listen_str);
3101
if (https_port_num >= 0) {
3102
announce_http(https_port_num, 1,
3105
announce_http(screen->httpPort, 2, listen_str);
3106
} else if (use_stunnel) {
3107
announce_http(screen->httpPort, 2, listen_str);
3109
announce_http(screen->httpPort, 0, listen_str);
3115
; /* should not occur (port != 0) */
3117
fprintf(stdout, "PORT=%d\n", screen->port);
3119
fprintf(stdout, "SSLPORT=%d\n", stunnel_port);
3120
} else if (use_openssl) {
3121
fprintf(stdout, "SSLPORT=%d\n", screen->port);
3125
FILE *flag = fopen(flagfile, "w");
3127
fprintf(flag, "PORT=%d\n",screen->port);
3129
fprintf(flag, "SSL_PORT=%d\n",
3135
rfbLog("could not open flag file: %s\n",