comparison src/browser.c @ 4428:b5669740e34c

[gaim-migrate @ 4703] Two patches from Ray Strode to clean up browser launching (esp. Netscape and Mozilla) and to show only available browsers in the prefs drop down list. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Sun, 26 Jan 2003 19:39:43 +0000
parents 02f4eacf4c58
children bf770f11132b
comparison
equal deleted inserted replaced
4427:88920ce27a9f 4428:b5669740e34c
32 #endif 32 #endif
33 #ifdef _WIN32 33 #ifdef _WIN32
34 #include <gdk/gdkwin32.h> 34 #include <gdk/gdkwin32.h>
35 #else 35 #else
36 #include <unistd.h> 36 #include <unistd.h>
37 #ifndef HOST_NAME_MAX
38 #define HOST_NAME_MAX 255
39 #endif
37 #include <gdk/gdkx.h> 40 #include <gdk/gdkx.h>
38 #endif 41 #endif
39 #include <stdio.h> 42 #include <stdio.h>
40 #include <stdlib.h> 43 #include <stdlib.h>
41 #include <string.h> 44 #include <string.h>
67 static GdkAtom GDKA_MOZILLA_VERSION = 0; 70 static GdkAtom GDKA_MOZILLA_VERSION = 0;
68 static GdkAtom GDKA_MOZILLA_LOCK = 0; 71 static GdkAtom GDKA_MOZILLA_LOCK = 0;
69 static GdkAtom GDKA_MOZILLA_COMMAND = 0; 72 static GdkAtom GDKA_MOZILLA_COMMAND = 0;
70 static GdkAtom GDKA_MOZILLA_RESPONSE = 0; 73 static GdkAtom GDKA_MOZILLA_RESPONSE = 0;
71 74
75 static char *window_check_mozilla_version(Window);
76 static const char *get_lock_data();
77 static GdkFilterReturn netscape_response_cb(XEvent *, GdkEvent *, GdkWindow *);
78 static gboolean netscape_command(const char *);
72 79
73 static int netscape_lock; 80 static int netscape_lock;
74 81
75 82
76 static Window VirtualRootWindowOfScreen(screen) 83 static Window VirtualRootWindowOfScreen(screen)
200 GDKA_MOZILLA_COMMAND = gdk_atom_intern(MOZILLA_COMMAND_PROP, 0); 207 GDKA_MOZILLA_COMMAND = gdk_atom_intern(MOZILLA_COMMAND_PROP, 0);
201 if (!GDKA_MOZILLA_RESPONSE) 208 if (!GDKA_MOZILLA_RESPONSE)
202 GDKA_MOZILLA_RESPONSE = gdk_atom_intern(MOZILLA_RESPONSE_PROP, 0); 209 GDKA_MOZILLA_RESPONSE = gdk_atom_intern(MOZILLA_RESPONSE_PROP, 0);
203 } 210 }
204 211
212 static char *window_check_mozilla_version(Window window) {
213
214 Atom type;
215 int format;
216 unsigned long nitems, bytesafter;
217 unsigned char *version = 0;
218 gchar *retval = NULL;
219
220 if (XGetWindowProperty(gdk_display, window,
221 gdk_x11_atom_to_xatom(GDKA_MOZILLA_VERSION),
222 0, (65536 / sizeof(long)),
223 False, XA_STRING,
224 &type, &format, &nitems, &bytesafter,
225 &version) != Success) {
226 return NULL;
227 }
228
229 if (!version) {
230 return NULL;
231 }
232
233 retval = g_strdup(version);
234 XFree(version);
235
236 return retval;
237 }
238
205 static GdkWindow *mozilla_remote_find_window() 239 static GdkWindow *mozilla_remote_find_window()
206 { 240 {
207 int i; 241 int i;
208 Window root = VirtualRootWindowOfScreen(DefaultScreenOfDisplay(gdk_display)); 242 Window root = VirtualRootWindowOfScreen(DefaultScreenOfDisplay(gdk_display));
209 Window root2, parent, *kids; 243 Window root2, parent, *kids;
210 unsigned int nkids; 244 unsigned int nkids;
211 Window result = 0; 245 Window result = 0;
212 Window tenative = 0; 246 Window tenative = 0;
213 unsigned char *tenative_version = 0; 247 unsigned char *tenative_version = 0, *version = 0;
248 static GdkWindow *remote_window = NULL;
249
250 if (remote_window != NULL) {
251 version = window_check_mozilla_version(GDK_WINDOW_XID(remote_window));
252
253 if (version != NULL) {
254 g_free(version);
255 return remote_window;
256 }
257 g_free(version);
258
259 gdk_window_destroy(remote_window);
260 remote_window = NULL;
261 }
214 262
215 if (!XQueryTree(gdk_display, root, &root2, &parent, &kids, &nkids)) { 263 if (!XQueryTree(gdk_display, root, &root2, &parent, &kids, &nkids)) {
216 debug_printf("%s: XQueryTree failed on display %s\n", progname, 264 debug_printf("%s: XQueryTree failed on display %s\n", progname,
217 DisplayString(gdk_display)); 265 DisplayString(gdk_display));
218 return NULL; 266 return NULL;
225 progname, DisplayString(gdk_display)); 273 progname, DisplayString(gdk_display));
226 return NULL; 274 return NULL;
227 } 275 }
228 276
229 for (i = nkids - 1; i >= 0; i--) { 277 for (i = nkids - 1; i >= 0; i--) {
230 Atom type;
231 int format;
232 unsigned long nitems, bytesafter;
233 unsigned char *version = 0;
234 Window w = GClientWindow(gdk_display, kids[i]); 278 Window w = GClientWindow(gdk_display, kids[i]);
235 int status = XGetWindowProperty(gdk_display, w, 279
236 gdk_x11_atom_to_xatom(GDKA_MOZILLA_VERSION), 280 version = window_check_mozilla_version(w);
237 0, (65536 / sizeof(long)), 281
238 False, XA_STRING, 282 if (version == NULL) {
239 &type, &format, &nitems, &bytesafter,
240 &version);
241
242 if (!version)
243 continue; 283 continue;
284 }
244 285
245 if (strcmp((char *)version, expected_mozilla_version) && !tenative) { 286 if (strcmp((char *)version, expected_mozilla_version) && !tenative) {
246 tenative = w; 287 tenative = w;
247 tenative_version = version; 288 tenative_version = version;
248 continue; 289 continue;
249 } 290 }
250 XFree(version); 291
251 if (status == Success && type != None) { 292 g_free(version);
293
252 result = w; 294 result = w;
253 break; 295 break;
254 } 296 }
255 }
256 297
257 XFree(kids); 298 XFree(kids);
258 299
259 if (result && tenative) { 300 if (result && tenative) {
260 debug_printf("%s: warning: both version %s (0x%x) and version\n" 301 debug_printf("%s: warning: both version %s (0x%x) and version\n"
277 return NULL; 318 return NULL;
278 } 319 }
279 } 320 }
280 321
281 322
282 static char *lock_data = 0; 323 static const char *get_lock_data() {
283 324 static char *lock_data = NULL;
284 static void mozilla_remote_obtain_lock(GdkWindow * window) 325
285 { 326 if (lock_data == NULL) {
286 Bool locked = False; 327 char hostname[HOST_NAME_MAX + 1] = {0};
287 328
288 if (!lock_data) { 329 if (gethostname(hostname, HOST_NAME_MAX + 1) == 0) {
289 lock_data = (char *)g_malloc(255); 330 lock_data = g_strdup_printf("pid%d@%s", getpid(), hostname);
290 sprintf(lock_data, "pid%d@", getpid()); 331 } else {
291 if (gethostname(lock_data + strlen(lock_data), 100)) { 332 lock_data = g_strdup_printf("pid%d", getpid());
292 return; 333 }
293 } 334 }
294 } 335
295 336 return lock_data;
296 do { 337 }
338
339 static gboolean mozilla_remote_obtain_lock(GdkWindow * window)
340 {
341 gboolean locked = False;
342 const char *lock_data = get_lock_data();
297 int result; 343 int result;
298 GdkAtom actual_type; 344 GdkAtom actual_type;
299 gint actual_format; 345 gint actual_format;
300 gint nitems; 346 gint nitems;
301 unsigned char *data = 0; 347 unsigned char *data = 0;
302 348
303 result = gdk_property_get(window, GDKA_MOZILLA_LOCK, 349 gdk_x11_grab_server();
350 if (!gdk_property_get(window, GDKA_MOZILLA_LOCK,
304 gdk_x11_xatom_to_atom (XA_STRING), 0, 351 gdk_x11_xatom_to_atom (XA_STRING), 0,
305 (65536 / sizeof(long)), 0, 352 (65536 / sizeof(long)), 0,
306 &actual_type, &actual_format, &nitems, &data); 353 &actual_type, &actual_format, &nitems, &data)) {
307 if (result != Success || actual_type == None) { 354
308 /* It's not now locked - lock it. */ 355 /* It's not now locked - lock it. */
309 debug_printf("%s: (writing " MOZILLA_LOCK_PROP 356 debug_printf("%s: (writing " MOZILLA_LOCK_PROP " \"%s\" to 0x%x)\n",
310 " \"%s\" to 0x%x)\n", progname, lock_data, (unsigned int)window); 357 progname, lock_data, (unsigned int) window);
311 358
312 gdk_property_change(window, GDKA_MOZILLA_LOCK, 359 gdk_property_change(window, GDKA_MOZILLA_LOCK,
313 gdk_x11_xatom_to_atom (XA_STRING), 360 gdk_x11_xatom_to_atom (XA_STRING),
314 8, PropModeReplace, 361 8, PropModeReplace,
315 (unsigned char *)lock_data, strlen(lock_data)); 362 (unsigned char *)lock_data, strlen(lock_data));
316 locked = True; 363 locked = True;
317 } 364 }
318 365
319 if (!locked) {
320 /* Then just fuck it. */
321 if (data) 366 if (data)
322 g_free(data); 367 g_free(data);
323 return; 368 gdk_x11_ungrab_server();
324 }
325 if (data)
326 g_free(data);
327 } while (!locked);
328 } 369 }
329 370
330 371
331 static void mozilla_remote_free_lock(GdkWindow * window) 372 static void mozilla_remote_free_lock(GdkWindow * window)
332 { 373 {
333 int result = 0; 374 int result = 0;
334 GdkAtom actual_type; 375 GdkAtom actual_type;
335 gint actual_format; 376 gint actual_format;
336 gint nitems; 377 gint nitems;
337 unsigned char *data = 0; 378 unsigned char *data = 0;
379 const char *lock_data = get_lock_data();
338 380
339 debug_printf("%s: (deleting " MOZILLA_LOCK_PROP 381 debug_printf("%s: (deleting " MOZILLA_LOCK_PROP
340 " \"%s\" from 0x%x)\n", progname, lock_data, (unsigned int)window); 382 " \"%s\" from 0x%x)\n", progname, lock_data, (unsigned int)window);
341 383
342 result = gdk_property_get(window, GDKA_MOZILLA_LOCK, 384 result = gdk_property_get(window, GDKA_MOZILLA_LOCK,
343 gdk_x11_xatom_to_atom (XA_STRING), 385 gdk_x11_xatom_to_atom (XA_STRING),
344 0, (65536 / sizeof(long)), 386 0, (65536 / sizeof(long)),
345 1, &actual_type, &actual_format, &nitems, &data); 387 1, &actual_type, &actual_format, &nitems, &data);
346 if (result != Success) { 388
389 if (result != TRUE) {
347 debug_printf("%s: unable to read and delete " MOZILLA_LOCK_PROP " property\n", progname); 390 debug_printf("%s: unable to read and delete " MOZILLA_LOCK_PROP " property\n", progname);
348 return; 391 return;
349 } else if (!data || !*data) { 392 } else if (!data || !*data) {
350 debug_printf("%s: invalid data on " MOZILLA_LOCK_PROP 393 debug_printf("%s: invalid data on " MOZILLA_LOCK_PROP
351 " of window 0x%x.\n", progname, (unsigned int)window); 394 " of window 0x%x.\n", progname, (unsigned int)window);
354 debug_printf("%s: " MOZILLA_LOCK_PROP 397 debug_printf("%s: " MOZILLA_LOCK_PROP
355 " was stolen! Expected \"%s\", saw \"%s\"!\n", progname, lock_data, data); 398 " was stolen! Expected \"%s\", saw \"%s\"!\n", progname, lock_data, data);
356 return; 399 return;
357 } 400 }
358 401
359 if (data) 402 XFree(data);
360 g_free(data); 403 }
361 } 404
362 405 static GdkFilterReturn netscape_response_cb(XEvent *event, GdkEvent *translated, GdkWindow *window)
363 406 {
364 static int mozilla_remote_command(GdkWindow * window, const char *command, Bool raise_p) 407 Atom actual_type, mozilla_response;
408 Window xid;
409 int actual_format;
410 unsigned long nitems, bytes_after;
411 unsigned char *data = 0;
412 char *error = NULL;
413
414 if (window == NULL || GDK_WINDOW_OBJECT(window)->destroyed) {
415 do_error_dialog(_("Communication with the browser failed. Please close all "
416 "windows and try again."), NULL, GAIM_ERROR);
417 debug_printf("netscape_response_cb called with NULL window.\n");
418 return GDK_FILTER_CONTINUE;
419 }
420
421 mozilla_response = gdk_x11_atom_to_xatom(GDKA_MOZILLA_RESPONSE);
422 xid = GDK_WINDOW_XID(window);
423
424 /* If the event isn't what we want then let gtk handle it */
425 if (event->xany.type != PropertyNotify ||
426 event->xproperty.state != PropertyNewValue ||
427 event->xproperty.window != xid ||
428 event->xproperty.atom != mozilla_response) {
429 return GDK_FILTER_CONTINUE;
430 }
431
432 if (XGetWindowProperty (gdk_display, xid, mozilla_response,
433 0, (65536 / sizeof (long)),
434 True,
435 XA_STRING,
436 &actual_type, &actual_format,
437 &nitems, &bytes_after,
438 &data) != Success
439 || data == NULL || (data[0] != '1' && data[0] != '2')) {
440
441 do_error_dialog(_("Communication with the browser failed. Please close all "
442 "windows and try again."), NULL, GAIM_ERROR);
443 }
444
445 if (data[0] == '1') {
446 /* Netscape isn't ready yet */
447 debug_printf("Remote Netscape window isn't ready yet.\n");
448 return GDK_FILTER_REMOVE;
449 }
450
451 if (data[0] == '2') {
452 /* Yay! It worked */
453 debug_printf("Successfully sent command to remote Netscape window.\n");
454 }
455
456 gdk_window_remove_filter(window, (GdkFilterFunc) netscape_response_cb, window);
457 mozilla_remote_free_lock(window);
458 netscape_lock = 0;
459 return GDK_FILTER_REMOVE;
460 }
461
462 static void mozilla_remote_command(GdkWindow * window, const char *command, Bool raise_p)
365 { 463 {
366 int result = 0; 464 int result = 0;
367 Bool done = False; 465 Bool done = False;
368 char *new_command = 0; 466 char *new_command = 0;
369 467