diff options
author | runge <runge> | 2005-07-07 01:45:21 +0000 |
---|---|---|
committer | runge <runge> | 2005-07-07 01:45:21 +0000 |
commit | 8fcf08613247c17aab767476fca6870bb45480a9 (patch) | |
tree | 27e5c932aeef9f47ee7e3a246da15b810f1401fb /x11vnc/x11vnc.c | |
parent | c59929365c6b73d89fd0ccbdcb223c0ec44a4d40 (diff) | |
download | libtdevnc-8fcf08613247c17aab767476fca6870bb45480a9.tar.gz libtdevnc-8fcf08613247c17aab767476fca6870bb45480a9.zip |
x11vnc: -gui tray now embeds in systray; more improvements to gui.
Diffstat (limited to 'x11vnc/x11vnc.c')
-rw-r--r-- | x11vnc/x11vnc.c | 682 |
1 files changed, 598 insertions, 84 deletions
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 04e02e8..0d30ef8 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -382,7 +382,7 @@ double xdamage_scheduled_mark = 0.0; sraRegionPtr xdamage_scheduled_mark_region = NULL; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.7.2 lastmod: 2005-07-01"; +char lastmod[] = "0.7.2 lastmod: 2005-07-06"; int hack_val = 0; /* X display info */ @@ -593,6 +593,7 @@ int count_added_keycodes(void); double dtime(double *); double dtime0(double *); double dnow(void); +double dnowx(void); void initialize_blackouts(char *); void initialize_blackouts_and_xinerama(void); @@ -615,6 +616,7 @@ void initialize_xinerama(void); void initialize_xfixes(void); void initialize_xdamage(void); int valid_window(Window, XWindowAttributes *, int); +Window parent_window(Window, char**); int xtranslate(Window, Window, int, int, int*, int*, Window*, int); void create_xdamage_if_needed(void); void destroy_xdamage_if_needed(void); @@ -749,6 +751,8 @@ void push_black_screen(int); void push_sleep(int); void refresh_screen(int); +int tray_embed(Window, int); +int tray_manager_running(Display *, Window *); /* -- options.h -- */ /* @@ -841,11 +845,22 @@ int flash_cmap = 0; /* follow installed colormaps */ int shift_cmap = 0; /* ncells < 256 and needs shift of pixel values */ int force_indexed_color = 0; /* whether to force indexed color for 8bpp */ int launch_gui = 0; /* -gui */ - -int tray_mode = 0; /* hack for -gui tray */ -char *tray_mode_file = NULL; -char *tray_mode_params = NULL; -FILE *tray_mode_fh = NULL; +char *gui_geometry = NULL; + +int icon_mode = 0; /* hack for -gui tray */ +int icon_in_tray = 0; +char *icon_mode_file = NULL; +char *icon_mode_params = NULL; +char *icon_mode_embed_id = NULL; +char *icon_mode_font = NULL; +FILE *icon_mode_fh = NULL; +#define ICON_MODE_SOCKS 16 +int icon_mode_socks[ICON_MODE_SOCKS]; + +int tray_manager_ok = 0; +Window tray_request = None; +Window tray_window = None; +int tray_unembed = 0; int use_modifier_tweak = 1; /* use the shift/altgr modifier tweak */ int use_iso_level3 = 0; /* ISO_Level3_Shift instead of Mode_switch */ @@ -864,6 +879,7 @@ int debug_xevents = 0; /* -R debug_xevents:1 */ int debug_xdamage = 0; /* -R debug_xdamage:1 or 2 ... */ int debug_wireframe = 0; int debug_tiles = 0; +int debug_grabs = 0; int xtrap_input = 0; /* -xtrap for user input insertion */ int xinerama = 0; /* -xinerama */ @@ -2940,6 +2956,12 @@ void disable_grabserver(Display *in_dpy, int change) { int ok = 0; static int didmsg = 0; + if (debug_grabs) { + fprintf(stderr, "disable_grabserver/%d %.5f\n", + xserver_grabbed, dnowx()); + didmsg = 0; + } + if (! xtrap_input) { if (XTestGrabControl_wr(in_dpy, True)) { if (change) { @@ -3029,6 +3051,11 @@ void xrecord_grabserver(int start) { XErrorHandler old_handler = NULL; int rc; + if (debug_grabs) { + fprintf(stderr, "xrecord_grabserver%d/%d %.5f\n", + xserver_grabbed, start, dnowx()); + } + if (! gdpy_ctrl || ! gdpy_data) { return; } @@ -3075,6 +3102,9 @@ void xrecord_grabserver(int start) { XSetErrorHandler(old_handler); XFlush(gdpy_data); #endif + if (debug_grabs) { + fprintf(stderr, "xrecord_grabserver-done: %.5f\n", dnowx()); + } } void initialize_xrecord(void) { @@ -3165,6 +3195,11 @@ void initialize_xrecord(void) { void shutdown_xrecord(void) { #if LIBVNCSERVER_HAVE_RECORD + if (debug_grabs) { + fprintf(stderr, "shutdown_xrecord%d %.5f\n", + xserver_grabbed, dnowx()); + } + if (rr_CA) XFree(rr_CA); if (rr_CW) XFree(rr_CW); if (rr_GS) XFree(rr_GS); @@ -3208,6 +3243,10 @@ void shutdown_xrecord(void) { X_UNLOCK; #endif use_xrecord = 0; + + if (debug_grabs) { + fprintf(stderr, "shutdown_xrecord-done: %.5f\n", dnowx()); + } } int xrecord_skip_keysym(rfbKeySym keysym) { @@ -4190,6 +4229,8 @@ void record_grab(XPointer ptr, XRecordInterceptData *rec_data) { xReq *req; int db = 0; + if (debug_grabs) db = 1; + /* should handle control msgs, start/stop/etc */ if (rec_data->category == XRecordStartOfData) { ; @@ -4246,7 +4287,7 @@ void check_xrecord_grabserver(void) { return; } -if (0) dtime0(&d); + dtime0(&d); XFlush(gdpy_ctrl); for (i=0; i<max; i++) { last_val = xserver_grabbed; @@ -4260,7 +4301,7 @@ if (0) dtime0(&d); if (cnt) { XFlush(gdpy_ctrl); } -if (0) { +if (debug_grabs && cnt > 0) { d = dtime(&d); fprintf(stderr, "check_xrecord_grabserver: cnt=%d i=%d %.4f\n", cnt, i, d); } @@ -4469,7 +4510,7 @@ if (0) db = 1; check_xrecord_grabserver(); X_UNLOCK; if (xserver_grabbed) { -if (db) fprintf(stderr, "xrecord_watch: %d/%d out xserver_grabbed\n", start, setby); +if (db || debug_grabs) fprintf(stderr, "xrecord_watch: %d/%d out xserver_grabbed\n", start, setby); return; } } @@ -4477,7 +4518,7 @@ if (db) fprintf(stderr, "xrecord_watch: %d/%d out xserver_grabbed\n", start, se #if LIBVNCSERVER_HAVE_RECORD if (! start) { int shut_reopen = 2, shut_time = 25; -if (db) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start); +if (db || debug_grabs) fprintf(stderr, "XRECORD OFF: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start); xrecording = 0; if (! rc_scroll) { xrecord_focus_window = None; @@ -4592,7 +4633,7 @@ if (db > 1) fprintf(stderr, "=== disab-scroll 0x%lx 0x%lx\n", rc_scroll, rcs_scr rcs_scroll = 0; return; } -if (db) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start); +if (db || debug_grabs) fprintf(stderr, "XRECORD ON: %d/%d %.4f\n", xrecording, setby, now - x11vnc_start); if (xrecording) { return; @@ -4893,15 +4934,15 @@ void clean_shm(int quick) { } } -void clean_tray_mode(void) { - if (tray_mode && tray_mode_fh) { - fprintf(tray_mode_fh, "quit\n"); - fflush(tray_mode_fh); - fclose(tray_mode_fh); - tray_mode_fh = NULL; - if (tray_mode_file) { - unlink(tray_mode_file); - tray_mode_file = NULL; +void clean_icon_mode(void) { + if (icon_mode && icon_mode_fh) { + fprintf(icon_mode_fh, "quit\n"); + fflush(icon_mode_fh); + fclose(icon_mode_fh); + icon_mode_fh = NULL; + if (icon_mode_file) { + unlink(icon_mode_file); + icon_mode_file = NULL; } } } @@ -4912,8 +4953,8 @@ void clean_tray_mode(void) { void clean_up_exit (int ret) { exit_flag = 1; - if (tray_mode) { - clean_tray_mode(); + if (icon_mode) { + clean_icon_mode(); } /* remove the shm areas: */ @@ -5172,8 +5213,8 @@ void interrupted (int sig) { X_UNLOCK; - if (tray_mode) { - clean_tray_mode(); + if (icon_mode) { + clean_icon_mode(); } /* remove the shm areas with quick=1: */ clean_shm(1); @@ -5207,6 +5248,27 @@ void interrupted (int sig) { } } +Window parent_window(Window win, char **name) { + Window r, parent; + Window *list; + unsigned int nchild; + + if (name != NULL) { + *name = NULL; + } + + if (! XQueryTree(dpy, win, &r, &parent, &list, &nchild)) { + return None; + } + if (list) { + XFree(list); + } + if (parent && name) { + XFetchName(dpy, parent, name); + } + return parent; +} + /* trapping utility to check for a valid window: */ int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet) { XErrorHandler old_handler; @@ -5219,6 +5281,10 @@ int valid_window(Window win, XWindowAttributes *attr_ret, int bequiet) { pattr = attr_ret; } + if (win == None) { + return 0; + } + trapped_xerror = 0; old_handler = XSetErrorHandler(trap_xerror); if (XGetWindowAttributes(dpy, win, pattr)) { @@ -6668,6 +6734,10 @@ void read_vnc_connect_prop(void) { vnc_connect_str[VNC_CONNECT_MAX] = '\0'; if (! db) { ; + } else if (strstr(vnc_connect_str, "ans=stop:N/A,ans=quit:N/A,ans=")) { + ; + } else if (strstr(vnc_connect_str, "qry=stop,quit,exit")) { + ; } else if (strstr(vnc_connect_str, "cmd=") && strstr(vnc_connect_str, "passwd")) { rfbLog("read VNC_CONNECT\n"); @@ -6816,10 +6886,136 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { return(RFB_CLIENT_ACCEPT); } +void start_client_info_sock(char *host_port_cookie) { + char *host = NULL, *cookie = NULL, *p; + char *str = strdup(host_port_cookie); + int i, port, sock, next = -1; + static time_t start_time[ICON_MODE_SOCKS]; + time_t oldest = 0; + int db = 0; + + for (i = 0; i < ICON_MODE_SOCKS; i++) { + if (icon_mode_socks[i] < 0) { + next = i; + break; + } + if (oldest == 0 || start_time[i] < oldest) { + next = i; + oldest = start_time[i]; + } + } + + p = strtok(str, ":"); + i = 0; + while (p) { + if (i == 0) { + host = strdup(p); + } else if (i == 1) { + port = atoi(p); + } else if (i == 2) { + cookie = strdup(p); + } + i++; + p = strtok(NULL, ":"); + } + free(str); + + if (db) fprintf(stderr, "%s/%d/%s next=%d\n", host, port, cookie, next); + + if (host && port && cookie) { + if (*host == '\0') { + free(host); + host = strdup("localhost"); + } + sock = rfbConnectToTcpAddr(host, port); + if (sock < 0) { + usleep(200 * 1000); + sock = rfbConnectToTcpAddr(host, port); + } + if (sock >= 0) { + char *lst = list_clients(); + icon_mode_socks[next] = sock; + start_time[next] = time(0); + write(sock, "COOKIE:", strlen("COOKIE:")); + write(sock, cookie, strlen(cookie)); + write(sock, "\n", strlen("\n")); + write(sock, "none\n", strlen("none\n")); + write(sock, "none\n", strlen("none\n")); + write(sock, lst, strlen(lst)); + write(sock, "\n", strlen("\n")); + if (db) { + fprintf(stderr, "list: %s\n", lst); + } + free(lst); + rfbLog("client_info_sock to: %s:%d\n", host, port); + } else { + rfbLog("failed client_info_sock: %s:%d\n", host, port); + } + } else { + rfbLog("malformed client_info_sock: %s\n", host_port_cookie); + } + + if (host) free(host); + if (cookie) free(cookie); +} + +void send_client_info(char *str) { + int i; + static char *pstr = NULL; + static int len = 128; + + if (!str || strlen(str) == 0) { + return; + } + + if (!pstr) { + pstr = (char *)malloc(len); + } + if (strlen(str) + 2 > (size_t) len) { + free(pstr); + len *= 2; + pstr = (char *)malloc(len); + } + strcpy(pstr, str); + strcat(pstr, "\n"); + + if (icon_mode_fh) { + fprintf(icon_mode_fh, "%s", pstr); + fflush(icon_mode_fh); + } + + for (i=0; i<ICON_MODE_SOCKS; i++) { + int len, n, sock = icon_mode_socks[i]; + char *buf = pstr; + + if (sock < 0) { + continue; + } + + len = strlen(pstr); + while (len > 0) { + n = write(sock, buf, len); + if (n > 0) { + buf += n; + len -= n; + continue; + } + + if (n < 0 && errno == EINTR) { + continue; + } + close(sock); + icon_mode_socks[i] = -1; + break; + } + } +} + void check_new_clients(void) { static int last_count = 0; rfbClientIteratorPtr iter; rfbClientPtr cl; + int i, send_info = 0; if (client_count == last_count) { return; @@ -6835,10 +7031,7 @@ void check_new_clients(void) { return; } if (! client_count) { - if (tray_mode_fh) { - fprintf(tray_mode_fh, "none\n"); - fflush(tray_mode_fh); - } + send_client_info("none"); return; } @@ -6868,10 +7061,18 @@ void check_new_clients(void) { } rfbReleaseClientIterator(iter); - if (tray_mode_fh) { + if (icon_mode_fh) { + send_info++; + } + for (i = 0; i < ICON_MODE_SOCKS; i++) { + if (send_info || icon_mode_socks[i] >= 0) { + send_info++; + break; + } + } + if (send_info) { char *str = list_clients(); - fprintf(tray_mode_fh, "%s\n", str); - fflush(tray_mode_fh); + send_client_info(str); free(str); } } @@ -11777,6 +11978,16 @@ void check_xevents(void) { last_bell = now; check_bell_event(); } + if (tray_request != None) { + static time_t last_tray_request = 0; + if (now > last_tray_request + 2) { + last_tray_request = now; + if (tray_embed(tray_request, tray_unembed)) { + tray_window = tray_request; + tray_request = None; + } + } + } #ifndef DEBUG_XEVENTS #define DEBUG_XEVENTS 1 @@ -13229,9 +13440,9 @@ char *process_remote_cmd(char *cmd, int stringonly) { } p += strlen("accept:"); if (safe_remote_only) { - if (tray_mode && !strcmp(p, "")) { + if (icon_mode && !strcmp(p, "")) { ; - } else if (tray_mode && !strcmp(p, "popup")) { + } else if (icon_mode && !strcmp(p, "popup")) { ; } else { rfbLog("unsafe: %s\n", p); @@ -15214,6 +15425,21 @@ char *process_remote_cmd(char *cmd, int stringonly) { debug_tiles = atoi(p); rfbLog("set debug_tiles to: %d\n", debug_tiles); + } else if (!strcmp(p, "debug_grabs")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, debug_grabs); + goto qry; + } + debug_grabs = 1; + rfbLog("set debug_grabs to: %d\n", debug_grabs); + } else if (!strcmp(p, "nodebug_grabs")) { + if (query) { + snprintf(buf, bufn, "ans=%s:%d", p, !debug_grabs); + goto qry; + } + debug_grabs = 0; + rfbLog("set debug_grabs to: %d\n", debug_grabs); + } else if (!strcmp(p, "dbg")) { if (query) { snprintf(buf, bufn, "ans=%s:%d", p, crash_debug); @@ -15248,7 +15474,18 @@ char *process_remote_cmd(char *cmd, int stringonly) { rfbLog("remote_cmd: disabling remote commands.\n"); accept_remote_cmds = 0; /* cannot be turned back on. */ - } else if (tray_mode && !query && strstr(p, "passwd") == p) { /* skip-cmd-list */ + } else if (strstr(p, "client_info_sock") == p) { /* skip-cmd-list */ + NOTAPP + p += strlen("client_info_sock:"); + if (*p != '\0') { + start_client_info_sock(p); + } + + } else if (strstr(p, "noop") == p) { + NOTAPP + rfbLog("remote_cmd: noop\n"); + + } else if (icon_mode && !query && strstr(p, "passwd") == p) { /* skip-cmd-list */ char **passwds_new = (char **) malloc(3*sizeof(char *)); char **passwds_old = (char **) screen->authPasswdData; @@ -15272,7 +15509,7 @@ char *process_remote_cmd(char *cmd, int stringonly) { } rfbLog("remote_cmd: changed full access passwd.\n"); - } else if (tray_mode && !query && strstr(p, "viewpasswd") == p) { /* skip-cmd-list */ + } else if (icon_mode && !query && strstr(p, "viewpasswd") == p) { /* skip-cmd-list */ char **passwds_new = (char **) malloc(3*sizeof(char *)); char **passwds_old = (char **) screen->authPasswdData; @@ -15299,6 +15536,32 @@ char *process_remote_cmd(char *cmd, int stringonly) { screen->authPasswdData = (void*) passwds_new; rfbLog("remote_cmd: changed view only passwd.\n"); + } else if (strstr(p, "trayembed") == p) { /* skip-cmd-list */ + unsigned long id; + NOTAPP + + COLON_CHECK("trayembed:") + p += strlen("trayembed:"); + if (scan_hexdec(p, &id)) { + tray_request = (Window) id; + tray_unembed = 0; + rfbLog("remote_cmd: will try to embed 0x%x in" + " the system tray.\n", id); + } + } else if (strstr(p, "trayunembed") == p) { /* skip-cmd-list */ + unsigned long id; + NOTAPP + + COLON_CHECK("trayunembed:") + p += strlen("trayunembed:"); + if (scan_hexdec(p, &id)) { + tray_request = (Window) id; + tray_unembed = 1; + rfbLog("remote_cmd: will try to unembed 0x%x out" + " of the system tray.\n", id); + } + + } else if (query) { /* read-only variables that can only be queried: */ @@ -23098,6 +23361,150 @@ int scan_for_updates(int count_only) { return tile_diffs; } +Window tweak_tk_window_id(Window win) { + char *name = NULL; + Window parent, new; + + /* hack for tk, does not report outermost window */ + new = win; + parent = parent_window(win, &name); + if (parent && name != NULL) { + lowercase(name); + if (strstr(name, "wish") || strstr(name, "x11vnc")) { + new = parent; + rfbLog("tray_embed: using parent: %s\n", name); + } + } + if (name != NULL) { + XFree(name); + } + return new; +} + +#define SYSTEM_TRAY_REQUEST_DOCK 0 +#define SYSTEM_TRAY_BEGIN_MESSAGE 1 +#define SYSTEM_TRAY_CANCEL_MESSAGE 2 +#define XEMBED_VERSION 0 +#define XEMBED_MAPPED (1 << 0) + +int tray_embed(Window iconwin, int remove) { + XEvent ev; + XErrorHandler old_handler; + Window manager; + Atom xembed_info; + Atom tatom; + XWindowAttributes attr; + long info[2] = {XEMBED_VERSION, XEMBED_MAPPED}; + long data = 0; + + if (remove) { + if (!valid_window(iconwin, &attr, 1)) { + return 0; + } + iconwin = tweak_tk_window_id(iconwin); + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + + /* + * unfortunately no desktops seem to obey this + * part of the XEMBED spec yet... + */ + XReparentWindow(dpy, iconwin, rootwin, 0, 0); + + XSetErrorHandler(old_handler); + if (trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; + return 1; + } + + xembed_info = XInternAtom(dpy, "_XEMBED_INFO", False); + if (xembed_info == None) { + return 0; + } + + if (!tray_manager_running(dpy, &manager)) { + return 0; + } + + memset(&ev, 0, sizeof(ev)); + ev.xclient.type = ClientMessage; + ev.xclient.window = manager; + ev.xclient.message_type = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", + False); + ev.xclient.format = 32; + ev.xclient.data.l[0] = CurrentTime; + ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK; + ev.xclient.data.l[2] = iconwin; + ev.xclient.data.l[3] = 0; + ev.xclient.data.l[4] = 0; + + if (!valid_window(iconwin, &attr, 1)) { + return 0; + } + + iconwin = tweak_tk_window_id(iconwin); + ev.xclient.data.l[2] = iconwin; + + XUnmapWindow(dpy, iconwin); + + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + + XSendEvent(dpy, manager, False, NoEventMask, &ev); + XSync(dpy, False); + + if (trapped_xerror) { + XSetErrorHandler(old_handler); + trapped_xerror = 0; + return 0; + } + + XChangeProperty(dpy, iconwin, xembed_info, xembed_info, 32, + PropModeReplace, (unsigned char *)&info, 2); + + /* kludge for KDE evidently needed... */ + tatom = XInternAtom(dpy, "KWM_DOCKWINDOW", False); + XChangeProperty(dpy, iconwin, tatom, tatom, 32, PropModeReplace, + (unsigned char *)&data, 1); + tatom = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False); + XChangeProperty(dpy, iconwin, tatom, XA_WINDOW, 32, PropModeReplace, + (unsigned char *)&data, 1); + + XSetErrorHandler(old_handler); + trapped_xerror = 0; + return 1; +} + +int tray_manager_running(Display *d, Window *manager) { + char tray_string[100]; + Atom tray_manager; + Window tray_win; + + if (manager) { + *manager = None; + } + sprintf(tray_string, "_NET_SYSTEM_TRAY_S%d", scr); + + tray_manager = XInternAtom(d, tray_string, True); + if (tray_manager == None) { + return 0; + } + + tray_win = XGetSelectionOwner(d, tray_manager); + if (manager) { + *manager = tray_win; + } + + if (tray_win == None) { + return 0; + } else { + return 1; + } +} + /* -- gui.c -- */ #ifdef NOGUI char gui_code[] = ""; @@ -23157,7 +23564,7 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, rootwin = RootWindow(dpy, scr); initialize_vnc_connect_prop(); } - usleep(1000*1000); + usleep(2200*1000); fprintf(stderr, "\n"); for (i=0; i<try_max; i++) { usleep(sleep*1000); @@ -23246,16 +23653,50 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, set_env("DISPLAY", gui_xdisplay); set_env("X11VNC_PROG", program_name); set_env("X11VNC_CMDLINE", program_cmdline); + set_env("X11VNC_WISHCMD", wish); if (simple_gui) { set_env("X11VNC_SIMPLE_GUI", "1"); } - if (tray_mode && tray_mode_file) { - set_env("X11VNC_TRAY_MODE", "1"); - set_env("X11VNC_CLIENT_FILE", tray_mode_file); - if (tray_mode_params) { - set_env("X11VNC_TRAY_EMBED_ID", tray_mode_params); + if (gui_geometry) { + set_env("X11VNC_GUI_GEOM", gui_geometry); + } + if (connect_to_x11vnc) { + set_env("X11VNC_STARTED", "1"); + } + if (icon_mode && icon_mode_file) { + set_env("X11VNC_ICON_MODE", "1"); + set_env("X11VNC_CLIENT_FILE", icon_mode_file); + if (icon_in_tray) { + if (tray_manager_ok) { + set_env("X11VNC_ICON_MODE", "TRAY:RUNNING"); + } else { + set_env("X11VNC_ICON_MODE", "TRAY"); + } + } else { + set_env("X11VNC_ICON_MODE", "ICON"); + } + if (icon_mode_params) { + char *p, *str = strdup(icon_mode_params); + p = strtok(str, ":-/,.+"); + while (p) { + if(strstr(p, "setp") == p) { + set_env("X11VNC_ICON_SETPASS", "1"); + } else if(strstr(p, "noadvanced") == p) { + set_env("X11VNC_ICON_NOADVANCED", "1"); + } else if(strstr(p, "minimal") == p) { + set_env("X11VNC_ICON_MINIMAL", "1"); + } else if (strstr(p, "0x") == p) { + set_env("X11VNC_ICON_EMBED_ID", p); + icon_mode_embed_id = strdup(p); + } + p = strtok(NULL, ":-/,.+"); + } + free(str); } } + if (icon_mode_font) { + set_env("X11VNC_ICON_FONT", icon_mode_font); + } if (no_external_cmds) { fprintf(stderr, "cannot run external commands in -nocmds " @@ -23269,10 +23710,10 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, tmpf = tmpfile(); if (tmpf == NULL) { /* if no tmpfile, use a pipe */ - if (tray_mode_params) { - if (strlen(tray_mode_params) < 20) { + if (icon_mode_embed_id) { + if (strlen(icon_mode_embed_id) < 20) { strcat(cmd, " -use "); - strcat(cmd, tray_mode_params); + strcat(cmd, icon_mode_embed_id); } } pipe = popen(cmd, "w"); @@ -23294,8 +23735,8 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui, rewind(tmpf); dup2(n, 0); close(n); - if (tray_mode_params) { - execlp(wish, wish, "-", "-use", tray_mode_params, + if (icon_mode_embed_id) { + execlp(wish, wish, "-", "-use", icon_mode_embed_id, (char *) NULL); } else { execlp(wish, wish, "-", (char *) NULL); @@ -23352,11 +23793,27 @@ void do_gui(char *opts) { connect_to_x11vnc = 1; } else if (!strcmp(p, "ez") || !strcmp(p, "simple")) { simple_gui = 1; - } else if (strstr(p, "tray") || strstr(p, "icon")) { + } else if (strstr(p, "iconfont") == p) { char *q; - tray_mode = 1; if ((q = strchr(p, '=')) != NULL) { - tray_mode_params = strdup(q+1); + icon_mode_font = strdup(q+1); + } + } else if (strstr(p, "tray") == p || strstr(p, "icon") == p) { + char *q; + icon_mode = 1; + if ((q = strchr(p, '=')) != NULL) { + icon_mode_params = strdup(q+1); + if (strstr(icon_mode_params, "setp")) { + deny_all = 1; + } + } + if (strstr(p, "tray") == p) { + icon_in_tray = 1; + } + } else if (strstr(p, "geom") == p) { + char *q; + if ((q = strchr(p, '=')) != NULL) { + gui_geometry = strdup(q+1); } } else { fprintf(stderr, "unrecognized gui opt: %s\n", p); @@ -23369,7 +23826,7 @@ void do_gui(char *opts) { connect_to_x11vnc = 1; } - if (tray_mode && !got_gui_xdisplay) { + if (icon_mode && !got_gui_xdisplay) { /* for tray mode, prefer the polled DISPLAY */ if (use_dpy) { if (gui_xdisplay) { @@ -23404,6 +23861,13 @@ void do_gui(char *opts) { gui_xdisplay); exit(1); } + if (icon_mode && icon_in_tray) { + if (tray_manager_running(test_dpy, NULL)) { + tray_manager_ok = 1; + } else { + tray_manager_ok = 0; + } + } XCloseDisplay(test_dpy); if (start_x11vnc) { @@ -23413,23 +23877,28 @@ void do_gui(char *opts) { int p; pid_t parent = getpid(); - if (tray_mode) { + if (icon_mode) { char tf[100]; + double dn = dnow(); struct stat sbuf; /* FIXME */ - sprintf(tf, "/tmp/x11vnc.tray.%d", (int) getpid()); + dn = dn - ((int) dn); + sprintf(tf, "/tmp/x11vnc.tray%d%d", (int) (1000000*dn), + (int) getpid()); unlink(tf); + /* race begins.. */ if (stat(tf, &sbuf) == 0) { - tray_mode = 0; + icon_mode = 0; } else { - tray_mode_fh = fopen(tf, "w"); - if (! tray_mode_fh) { - tray_mode = 0; + icon_mode_fh = fopen(tf, "w"); + if (! icon_mode_fh) { + icon_mode = 0; } else { - chmod(tf, 0600); - tray_mode_file = strdup(tf); - fprintf(tray_mode_fh, "none\n"); - fflush(tray_mode_fh); + chmod(tf, 0400); + icon_mode_file = strdup(tf); + fprintf(icon_mode_fh, "none\n"); + fprintf(icon_mode_fh, "none\n"); + fflush(icon_mode_fh); if (! got_connect_once) { /* want -forever for tray */ connect_once = 0; @@ -27747,6 +28216,10 @@ double dnow(void) { return dtime0(&t); } +double dnowx(void) { + return dnow() - x11vnc_start; +} + void measure_display_hook(rfbClientPtr cl) { ClientData *cd = (ClientData *) cl->clientData; dtime0(&cd->timer); @@ -29785,6 +30258,9 @@ static void print_help(int mode) { " currently used by the -scrollcopyrect scheme and to\n" " monitor X server grabs.\n" "\n" +"-debug_grabs Turn on debugging info printout with respect to\n" +" XGrabServer() deadlock for -scrollcopyrect mode.\n" +"\n" "-pointer_mode n Various pointer motion update schemes. \"-pm\" is\n" " an alias. The problem is pointer motion can cause\n" " rapid changes on the screen: consider the rapid changes\n" @@ -30032,9 +30508,10 @@ static void print_help(int mode) { " up on the X display in the environment variable DISPLAY.\n" "\n" " \"gui-opts\" can be a comma separated list of items.\n" -" Currently there are these types of items: 1) a gui mode,\n" -" a 2) gui \"simplicity\", 3) the X display the gui\n" -" should display on, and 4) a \"tray\" (or icon) mode.\n" +" Currently there are these types of items: 1) a gui\n" +" mode, a 2) gui \"simplicity\", 3) the X display the\n" +" gui should display on, 4) a \"tray\" or \"icon\" mode,\n" +" and 5) a gui geometry.\n" "\n" " 1) The gui mode can be \"start\", \"conn\", or \"wait\"\n" " \"start\" is the default mode above and is not required.\n" @@ -30067,22 +30544,44 @@ static void print_help(int mode) { " x11vnc polling :0 and display the gui on otherhost:0\n" " The \"tray\" mode below reverses this preference.\n" "\n" -" 4) When \"tray\" is specified, the gui presents itself\n" -" as a small icon with behavior similar to a \"system\n" -" tray\" or \"dock\" applet. The color of the icon\n" -" indicates status (connected clients) and there is also a\n" -" balloon status. Clicking on the icon gives a menu from\n" -" which properties, etc, can be set and the full gui is\n" -" available under \"Advanced\". To be fully functional,\n" -" the gui mode should be \"start\" (the default). At some\n" -" point it is hoped the icon can be automatically embedded\n" -" in common destkop trays/docks. Currently one can only\n" -" embed it in a window via, e.g., \"tray=0x3600028\".\n" -" Otherwise the icon is just a normal standalone window.\n" +" 4) When \"tray\" or \"icon\" is specified, the gui\n" +" presents itself as a small icon with behavior typical\n" +" of a \"system tray\" or \"dock\" applet. The color\n" +" of the icon indicates status (connected clients) and\n" +" there is also a balloon status. Clicking on the icon\n" +" gives a menu from which properties, etc, can be set and\n" +" the full gui is available under \"Advanced\". To be\n" +" fully functional, the gui mode should be \"start\"\n" +" (the default).\n" +"\n" +" For \"icon\" the gui just a small standalone window.\n" +" For \"tray\" it will attempt to embed itself in the\n" +" \"system tray\". If \"=setpass\" is appended then\n" +" at startup the X11 user will be prompted to set the\n" +" VNC session password. If =<hexnumber> is appended\n" +" that icon will attempt to embed itself in the window\n" +" given by hexnumber. Use =noadvanced to disable the\n" +" full gui. (To supply more than one, use \"+\" sign).\n" +" E.g. -gui tray=setpass and -gui icon=0x3600028\n" "\n" -" Examples: \"x11vnc -gui\", \"x11vnc -gui ez\"\n" -" \"x11vnc -gui localhost:10\", \"x11vnc -gui conn,host:0\"\n" -" \"x11vnc -gui tray,ez\"\n" +" 5) When \"geom=+X+Y\" is specified, that geometry\n" +" is passed to the gui toplevel. This is the icon in\n" +" icon/tray mode, or the full gui otherwise. You can\n" +" also specify width and height, i.e. WxH+X+Y, but it\n" +" is not recommended. In \"tray\" mode the geometry is\n" +" ignored unless the system tray manager does not seem\n" +" to be running. One could imagine using something like\n" +" \"-gui tray,geom=+4000+4000\" with a display manager\n" +" to keep the gui invisible until someone logs in...\n" +"\n" +" More icon tricks, \"icon=minimal\" gives an icon just\n" +" with the VNC display number. You can also set the font\n" +" with \"iconfont=...\". The following could be useful:\n" +" \"-gui icon=minimal,iconfont=5x8,geom=24x10+0-0\"\n" +"\n" +" General examples of the -gui option: \"x11vnc -gui\",\n" +" \"x11vnc -gui ez\" \"x11vnc -gui localhost:10\",\n" +" \"x11vnc -gui conn,host:0\", \"x11vnc -gui tray,ez\"\n" "\n" " If you do not intend to start x11vnc from the gui\n" " (i.e. just remote control an existing one), then the\n" @@ -30354,6 +30853,8 @@ static void print_help(int mode) { " nodebug_scroll disable debugging scrollcopy mechanism.\n" " debug_tiles enable -debug_tiles\n" " nodebug_tiles disable -debug_tiles\n" +" debug_grabs enable -debug_grabs\n" +" nodebug_grabs disable -debug_grabs\n" " dbg enable -dbg crash shell\n" " nodbg disable -dbg crash shell\n" "\n" @@ -30394,10 +30895,10 @@ static void print_help(int mode) { " truecolor notruecolor overlay nooverlay overlay_cursor\n" " overlay_yescursor nooverlay_nocursor nooverlay_cursor\n" " nooverlay_yescursor overlay_nocursor visual scale\n" -" scale_cursor viewonly noviewonly shared noshared\n" -" forever noforever once timeout deny lock nodeny unlock\n" -" connect allowonce allow localhost nolocalhost listen\n" -" lookup nolookup accept gone shm noshm flipbyteorder\n" +" scale_cursor viewonly noviewonly shared noshared forever\n" +" noforever once timeout deny lock nodeny unlock connect\n" +" allowonce allow localhost nolocalhost listen lookup\n" +" nolookup accept popup gone shm noshm flipbyteorder\n" " noflipbyteorder onetile noonetile solid_color solid\n" " nosolid blackout xinerama noxinerama xtrap noxtrap\n" " xrandr noxrandr xrandr_mode padgeom quiet q noquiet\n" @@ -30428,8 +30929,8 @@ static void print_help(int mode) { " debug_xevents debug_xdamage nodebug_xdamage\n" " debug_xdamage debug_wireframe nodebug_wireframe\n" " debug_wireframe debug_scroll nodebug_scroll debug_scroll\n" -" debug_tiles dbt nodebug_tiles nodbt debug_tiles dbg\n" -" nodbg noremote\n" +" debug_tiles dbt nodebug_tiles nodbt debug_tiles\n" +" debug_grabs nodebug_grabs dbg nodbg noremote\n" "\n" " aro= display vncdisplay desktopname guess_desktop\n" " http_url auth users rootshift clipshift scale_str\n" @@ -30741,6 +31242,11 @@ static void check_rcfile(int argc, char **argv) { FILE *rc; for (i=1; i < argc; i++) { + if (!strcmp(argv[i], "-printgui")) { + fprintf(stdout, "%s", gui_code); + fflush(stdout); + exit(0); + } if (!strcmp(argv[i], "-norc")) { norc = 1; } @@ -31062,6 +31568,10 @@ int main(int argc, char* argv[]) { } } + for (i=0; i<ICON_MODE_SOCKS; i++) { + icon_mode_socks[i] = -1; + } + check_rcfile(argc, argv); /* kludge for the new array argv2 set in check_rcfile() */ # define argc argc2 @@ -31550,6 +32060,8 @@ int main(int argc, char* argv[]) { } else if (!strcmp(arg, "-debug_tiles") || !strcmp(arg, "-dbt")) { debug_tiles++; + } else if (!strcmp(arg, "-debug_grabs")) { + debug_grabs++; } else if (!strcmp(arg, "-snapfb")) { use_snapfb = 1; } else if (!strcmp(arg, "-rawfb")) { @@ -31606,6 +32118,8 @@ int main(int argc, char* argv[]) { xkbcompat = 0; } else if (!strcmp(arg, "-sync")) { remote_sync = 1; + } else if (!strcmp(arg, "-nosync")) { + remote_sync = 0; } else if (!strcmp(arg, "-noremote")) { accept_remote_cmds = 0; } else if (!strcmp(arg, "-yesremote")) { |