From 71f2ec79180185a6c3db0c87f9d53c491dc31e76 Mon Sep 17 00:00:00 2001 From: runge Date: Mon, 9 Jan 2006 01:54:38 +0000 Subject: x11vnc: the big split. --- x11vnc/gui.c | 638 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 638 insertions(+) create mode 100644 x11vnc/gui.c (limited to 'x11vnc/gui.c') diff --git a/x11vnc/gui.c b/x11vnc/gui.c new file mode 100644 index 0000000..9e6ac54 --- /dev/null +++ b/x11vnc/gui.c @@ -0,0 +1,638 @@ +/* -- gui.c -- */ + +#include "x11vnc.h" +#include "xevents.h" +#include "win_utils.h" +#include "remote.h" +#include "cleanup.h" + +#include "tkx11vnc.h" + +#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 icon_mode = 0; /* hack for -gui tray */ +char *icon_mode_file = NULL; +FILE *icon_mode_fh = NULL; +int icon_mode_socks[ICON_MODE_SOCKS]; +int tray_manager_ok = 0; +Window tray_request = None; +Window tray_window = None; +int tray_unembed = 0; + + +char *get_gui_code(void); +int tray_embed(Window iconwin, int remove); +void do_gui(char *opts, int sleep); + + +static Window tweak_tk_window_id(Window win); +static int tray_manager_running(Display *d, Window *manager); +static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, + int simple_gui, pid_t parent, char *gui_opts); + + +char *get_gui_code(void) { + return gui_code; +} + +static 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; +} + +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; +} + +static 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; + } +} + +static char *gui_geometry = NULL; +static int icon_in_tray = 0; +static char *icon_mode_embed_id = NULL; +static char *icon_mode_font = NULL; +static char *icon_mode_params = NULL; + +static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc, + int simple_gui, pid_t parent, char *gui_opts) { + char *x11vnc_xdisplay = NULL; + char extra_path[] = ":/usr/local/bin:/usr/bin/X11:/usr/sfw/bin" + ":/usr/X11R6/bin:/usr/openwin/bin:/usr/dt/bin"; + char cmd[100]; + char *wish = NULL, *orig_path, *full_path, *tpath, *p; + char *old_xauth = NULL; + int try_max = 4, sleep = 300; + pid_t mypid = getpid(); + FILE *pipe, *tmpf; + + if (*gui_code == '\0') { + rfbLog("gui: gui not compiled into this program.\n"); + exit(0); + } + if (getenv("DISPLAY") != NULL) { + /* worst case */ + x11vnc_xdisplay = strdup(getenv("DISPLAY")); + } + if (use_dpy) { + /* better */ + x11vnc_xdisplay = strdup(use_dpy); + } + if (connect_to_x11vnc) { + int rc, i; + rfbLogEnable(1); + if (! client_connect_file) { + if (getenv("XAUTHORITY") != NULL) { + old_xauth = strdup(getenv("XAUTHORITY")); + } else { + old_xauth = strdup(""); + } + dpy = XOpenDisplay(x11vnc_xdisplay); + if (! dpy && auth_file) { + set_env("XAUTHORITY", auth_file); + dpy = XOpenDisplay(x11vnc_xdisplay); + } + if (! dpy && ! x11vnc_xdisplay) { + /* worstest case */ + x11vnc_xdisplay = strdup(":0"); + dpy = XOpenDisplay(x11vnc_xdisplay); + } + if (! dpy) { + rfbLog("gui: could not open x11vnc " + "display: %s\n", NONUL(x11vnc_xdisplay)); + exit(1); + } + scr = DefaultScreen(dpy); + rootwin = RootWindow(dpy, scr); + initialize_vnc_connect_prop(); + } + usleep(2200*1000); + fprintf(stderr, "\n"); + if (!quiet) { + rfbLog("gui: trying to contact a x11vnc server at X" + " display %s ...\n", NONUL(x11vnc_xdisplay)); + } + for (i=0; i