Yo.
gtk1-stable
v0_59_9
2003-03-01, Sean Egan
* Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * some code: (most in this file) * Copyright (C) 1996 Netscape Communications Corporation, all rights reserved. * Created: Jamie Zawinski <jwz@netscape.com>, 24-Dec-94. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * This code is mainly taken from Netscape's sample implementation of #include <gdk/gdkprivate.h> static const char *progname = "gaim"; static const char *expected_mozilla_version = "1.1"; #define MOZILLA_VERSION_PROP "_MOZILLA_VERSION" #define MOZILLA_LOCK_PROP "_MOZILLA_LOCK" #define MOZILLA_COMMAND_PROP "_MOZILLA_COMMAND" #define MOZILLA_RESPONSE_PROP "_MOZILLA_RESPONSE" static GdkAtom XA_MOZILLA_VERSION = 0; static GdkAtom XA_MOZILLA_LOCK = 0; static GdkAtom XA_MOZILLA_COMMAND = 0; static GdkAtom XA_MOZILLA_RESPONSE = 0; static int netscape_lock; static Window VirtualRootWindowOfScreen(screen) static Screen *save_screen = (Screen *) 0; static Window root = (Window) 0; if (screen != save_screen) { Display *dpy = DisplayOfScreen(screen); Window rootReturn, parentReturn, *children; unsigned int numChildren; root = RootWindowOfScreen(screen); /* go look for a virtual root */ __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); if (XQueryTree(dpy, root, &rootReturn, &parentReturn, &children, &numChildren)) { for (i = 0; i < numChildren; i++) { unsigned long nitems, bytesafter; Window *newRoot = (Window *) 0; if (XGetWindowProperty(dpy, children[i], __SWM_VROOT, 0, 1, False, XA_WINDOW, &actual_type, &actual_format, (unsigned char **)&newRoot) == Success /* The following code is Copyright (C) 1989 X Consortium */ static Window TryChildren(); /* Find a window with WM_STATE, else return win itself, as per ICCCM */ static Window GClientWindow(dpy, win) unsigned long nitems, after; WM_STATE = XInternAtom(dpy, "WM_STATE", True); XGetWindowProperty(dpy, win, WM_STATE, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data); inf = TryChildren(dpy, win, WM_STATE); Window TryChildren(dpy, win, WM_STATE) unsigned long nitems, after; if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) for (i = 0; !inf && (i < nchildren); i++) { XGetWindowProperty(dpy, children[i], WM_STATE, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data); for (i = 0; !inf && (i < nchildren); i++) inf = TryChildren(dpy, children[i], WM_STATE); /* END X Consortium code */ static void mozilla_remote_init_atoms() XA_MOZILLA_VERSION = gdk_atom_intern(MOZILLA_VERSION_PROP, 0); XA_MOZILLA_LOCK = gdk_atom_intern(MOZILLA_LOCK_PROP, 0); XA_MOZILLA_COMMAND = gdk_atom_intern(MOZILLA_COMMAND_PROP, 0); if (!XA_MOZILLA_RESPONSE) XA_MOZILLA_RESPONSE = gdk_atom_intern(MOZILLA_RESPONSE_PROP, 0); static GdkWindow *mozilla_remote_find_window() Window root = VirtualRootWindowOfScreen(DefaultScreenOfDisplay(gdk_display)); Window root2, parent, *kids; unsigned char *tenative_version = 0; if (!XQueryTree(gdk_display, root, &root2, &parent, &kids, &nkids)) { debug_printf("%s: XQueryTree failed on display %s\n", progname, DisplayString(gdk_display)); /* root != root2 is possible with virtual root WMs. */ debug_printf("%s: root window has no children on display %s\n", progname, DisplayString(gdk_display)); for (i = nkids - 1; i >= 0; i--) { unsigned long nitems, bytesafter; unsigned char *version = 0; Window w = GClientWindow(gdk_display, kids[i]); int status = XGetWindowProperty(gdk_display, w, XA_MOZILLA_VERSION, 0, (65536 / sizeof(long)), &type, &format, &nitems, &bytesafter, if (strcmp((char *)version, expected_mozilla_version) && !tenative) { tenative_version = version; if (status == Success && type != None) { if (result && tenative) { debug_printf("%s: warning: both version %s (0x%x) and version\n" "\t%s (0x%x) are running. Using version %s.\n", progname, tenative_version, (unsigned int)tenative, expected_mozilla_version, (unsigned int)result, expected_mozilla_version); return gdk_window_foreign_new(result); debug_printf("%s: warning: expected version %s but found version\n" "\t%s (0x%x) instead.\n", progname, expected_mozilla_version, tenative_version, (unsigned int)tenative); return gdk_window_foreign_new(tenative); return gdk_window_foreign_new(result); debug_printf("%s: not running on display %s\n", progname, DisplayString(gdk_display)); static char *lock_data = 0; static void mozilla_remote_obtain_lock(GdkWindow * window) lock_data = (char *)g_malloc(255); sprintf(lock_data, "pid%d@", getpid()); if (gethostname(lock_data + strlen(lock_data), 100)) { result = gdk_property_get(window, XA_MOZILLA_LOCK, (65536 / sizeof(long)), 0, &actual_type, &actual_format, &nitems, &data); if (result != Success || actual_type == None) { /* It's not now locked - lock it. */ debug_printf("%s: (writing " MOZILLA_LOCK_PROP " \"%s\" to 0x%x)\n", progname, lock_data, (unsigned int)window); gdk_property_change(window, XA_MOZILLA_LOCK, XA_STRING, (unsigned char *)lock_data, strlen(lock_data)); static void mozilla_remote_free_lock(GdkWindow * window) debug_printf("%s: (deleting " MOZILLA_LOCK_PROP " \"%s\" from 0x%x)\n", progname, lock_data, (unsigned int)window); result = gdk_property_get(window, XA_MOZILLA_LOCK, XA_STRING, 0, (65536 / sizeof(long)), 1, &actual_type, &actual_format, &nitems, &data); debug_printf("%s: unable to read and delete " MOZILLA_LOCK_PROP " property\n", progname); } else if (!data || !*data) { debug_printf("%s: invalid data on " MOZILLA_LOCK_PROP " of window 0x%x.\n", progname, (unsigned int)window); } else if (strcmp((char *)data, lock_data)) { debug_printf("%s: " MOZILLA_LOCK_PROP " was stolen! Expected \"%s\", saw \"%s\"!\n", progname, lock_data, data); static int mozilla_remote_command(GdkWindow * window, const char *command, Bool raise_p) /* The -noraise option is implemented by passing a "noraise" argument to each command to which it should apply. new_command = g_malloc(strlen(command) + 20); strcpy(new_command, command); close = strrchr(new_command, ')'); strcpy(close, ", noraise)"); strcat(new_command, "(noraise)"); debug_printf("%s: (writing " MOZILLA_COMMAND_PROP " \"%s\" to 0x%x)\n", progname, command, (unsigned int)window); gdk_property_change(window, XA_MOZILLA_COMMAND, XA_STRING, 8, GDK_PROP_MODE_REPLACE, (unsigned char *)command, strlen(command)); if (event->any.window != window) { gtk_main_do_event(event); if (event->type == GDK_DESTROY && event->any.window == window) { /* Print to warn user... */ debug_printf("%s: window 0x%x was destroyed.\n", progname, (unsigned int)window); } else if (event->type == GDK_PROPERTY_NOTIFY && event->property.state == GDK_PROPERTY_NEW_VALUE && event->property.window == window && event->property.atom == XA_MOZILLA_RESPONSE) { gint actual_format, nitems; result = gdk_property_get(window, XA_MOZILLA_RESPONSE, 1, &actual_type, &actual_format, &nitems, &data); if (result == Success && data && *data) { debug_printf("%s: (server sent " MOZILLA_RESPONSE_PROP progname, data, (unsigned int)window); debug_printf("%s: failed reading " MOZILLA_RESPONSE_PROP " from window 0x%0x.\n", progname, (unsigned int)window); } else if (!data || strlen((char *)data) < 5) { debug_printf("%s: invalid data on " MOZILLA_RESPONSE_PROP " property of window 0x%0x.\n", progname, (unsigned int)window); } else if (*data == '1') { /* positive preliminary reply */ debug_printf("%s: %s\n", progname, data + 4); } else if (!strncmp((char *)data, "200", 3)) { } else if (*data == '2') { debug_printf("%s: %s\n", progname, data + 4); } else if (*data == '3') { debug_printf("%s: internal error: " "server wants more information? (%s)\n", progname, data); } else if (*data == '4' || *data == '5') { debug_printf("%s: %s\n", progname, data + 4); debug_printf("%s: unrecognised " MOZILLA_RESPONSE_PROP " from window 0x%x: %s\n", progname, (unsigned int)window, data); } else if (event->type == GDK_PROPERTY_NOTIFY && event->property.window == window && event->property.state == GDK_PROPERTY_DELETE && event->property.atom == XA_MOZILLA_COMMAND) { debug_printf("%s: (server 0x%x has accepted " MOZILLA_COMMAND_PROP ".)\n", progname, (unsigned int)window); gint check_netscape(char *msg) mozilla_remote_init_atoms(); window = mozilla_remote_find_window(); if (window && (((GdkWindowPrivate *) window)->destroyed == FALSE)) { XSelectInput(gdk_display, GDK_WINDOW_XWINDOW(window), (PropertyChangeMask | StructureNotifyMask)); mozilla_remote_obtain_lock(window); status = mozilla_remote_command(window, msg, False); mozilla_remote_free_lock(window); static void netscape_command(char *command) mozilla_remote_init_atoms(); window = mozilla_remote_find_window(); if (window && (((GdkWindowPrivate *) window)->destroyed == FALSE)) { XSelectInput(gdk_display, GDK_WINDOW_XWINDOW(window), (PropertyChangeMask | StructureNotifyMask)); mozilla_remote_obtain_lock(window); status = mozilla_remote_command(window, command, False); mozilla_remote_free_lock(window); gdk_window_destroy(window); args[0] = g_strdup("netscape"); e = execvp(args[0], args); printf("Hello%d\n", getppid()); char *tmp = g_strdup(command); gtk_timeout_add(200, (GtkFunction)check_netscape, tmp); void open_url(GtkWidget *w, char *url) if (web_browser == BROWSER_NETSCAPE) { if (misc_options & OPT_MISC_BROWSER_POPUP) command = g_strdup_printf("OpenURL(%s, new-window)", url); command = g_strdup_printf("OpenURL(%s)", url); netscape_command(command); } else if (web_browser == BROWSER_GNOME) { /* args will be allocated below but we don't bother * freeing it since we're just going to exec and if (web_browser == BROWSER_OPERA) { } else if (web_browser == BROWSER_KONQ) { } else if (web_browser == BROWSER_GALEON) { if (misc_options & OPT_MISC_BROWSER_POPUP) { } else if (web_browser == BROWSER_MOZILLA) { } else if (web_browser == BROWSER_MANUAL) { space_free_url = g_strdelimit(url, " ", '+'); g_snprintf(command, sizeof(command), web_command, space_free_url); args = g_strsplit(command, " ", 0); void add_bookmark(GtkWidget *w, char *url) if (web_browser == BROWSER_NETSCAPE) { char *command = g_malloc(1024); g_snprintf(command, 1024, "AddBookmark(%s)", url); netscape_command(command); /* Sooner or later, I shall support Windows clicking! */ void add_bookmark(GtkWidget *w, char *url) void open_url_nw(GtkWidget *w, char *url)