summaryrefslogtreecommitdiff
path: root/src/nautilus-view-frame.c
diff options
context:
space:
mode:
authorDarin Adler <darin@src.gnome.org>2001-03-29 01:39:07 +0000
committerDarin Adler <darin@src.gnome.org>2001-03-29 01:39:07 +0000
commit5df94af1979914c9d676764ad1d37cc7f2665520 (patch)
treeee3cbf871769300687fd81597ee1546465182005 /src/nautilus-view-frame.c
parent47601ce1d577e9f42e25fb35b62833d802c5f489 (diff)
downloadnautilus-5df94af1979914c9d676764ad1d37cc7f2665520.tar.gz
reviewed by: John Sullivan <sullivan@eazel.com>
A change to reduce the number of orphaned processes when Nautilus is not terminated cleanly. This is an architecture problem, and this hack only partly addresses it. Add code to NautilusViewFrame, NautilusView, and NautilusThrobber to destroy components when the corresponding widgets are destroyed. Since X destroys windows when processes go away, this tells us immediately when processes disappear. This does not help in the case where Nautilus happens to die after creating a component, but before attaching the widget to its parent. This is not a complete solution to the orphaned processes problem because of 2 other categories of orphaned processes: 1) the adapter factory 2) non-NautilusView components, which won't get the advantage of this fix because it's in Nautilus (a fix could go into Bonobo, or into each component) * libnautilus/nautilus-bonobo-workarounds.h: * libnautilus/nautilus-bonobo-workarounds.c: (set_gone_flag), (nautilus_bonobo_object_force_destroy), (object_is_gone), (remote_check_data_free), (remote_check_timed_callback), (remote_check_destroy_callback), (nautilus_bonobo_object_call_when_remote_object_disappears), (force_destroy_cover), (nautilus_bonobo_object_force_destroy_when_owner_disappears): New code, implementing the machinery to notice when remote objects go away and to self-destruct when they do. Also code that does the timeout that used to be in NautilusViewFrame. * libnautilus/nautilus-view.c: (widget_destroyed_callback), (nautilus_view_construct_from_bonobo_control): Connect to the widget's destroy signal, and self-destruct when it happens. * components/throbber/nautilus-throbber.c: (nautilus_throbber_destroy), (null_pointer_callback), (nautilus_throbber_initialize): Destroy the BonoboControl when the throbber (a widget) is destroyed. Requires noticing when the control goes away (the old code just had a stale pointer to it). * src/nautilus-view-frame.c: (destroy_view), (nautilus_view_frame_destroy), (view_frame_failed_callback), (queue_view_frame_failed), (view_frame_failed_cover), (check_socket_gone_idle_callback), (check_socket_gone_callback), (attach_view): Use the new machinery instead of doing it ourselves, but sadly had to add some fairly complex code to catch the case where the socket is destroyed because the plug is gone.
Diffstat (limited to 'src/nautilus-view-frame.c')
-rw-r--r--src/nautilus-view-frame.c151
1 files changed, 94 insertions, 57 deletions
diff --git a/src/nautilus-view-frame.c b/src/nautilus-view-frame.c
index 92b9155ad..209ca3a66 100644
--- a/src/nautilus-view-frame.c
+++ b/src/nautilus-view-frame.c
@@ -37,22 +37,16 @@
#include "nautilus-window.h"
#include <bonobo/bonobo-zoomable-frame.h>
#include <bonobo/bonobo-zoomable.h>
-#include <gtk/gtksignal.h>
#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
#include <libnautilus-extensions/nautilus-bonobo-extensions.h>
#include <libnautilus-extensions/nautilus-gtk-extensions.h>
#include <libnautilus-extensions/nautilus-gtk-macros.h>
#include <libnautilus-extensions/nautilus-undo-manager.h>
+#include <libnautilus/nautilus-bonobo-workarounds.h>
#include <libnautilus/nautilus-idle-queue.h>
#include <libnautilus/nautilus-view.h>
-/* FIXME bugzilla.eazel.com 2456: Is a hard-coded 12 seconds wait to
- * detect that a view is gone acceptable? Can a component that is
- * working still take 12 seconds to respond?
- */
-/* Milliseconds */
-#define VIEW_RESPONSE_TIMEOUT 12000
-
enum {
CHANGE_SELECTION,
CHANGE_STATUS,
@@ -101,13 +95,12 @@ struct NautilusViewFrameDetails {
BonoboUIContainer *ui_container;
NautilusUndoManager *undo_manager;
- guint check_if_view_is_gone_timeout_id;
-
NautilusBonoboActivationHandle *activation_handle;
NautilusIdleQueue *idle_queue;
- guint view_frame_failed_id;
+ guint failed_idle_id;
+ guint socket_gone_idle_id;
};
static void nautilus_view_frame_initialize (NautilusViewFrame *view);
@@ -339,6 +332,8 @@ destroy_view (NautilusViewFrame *view)
bonobo_object_release_unref (view->details->view, NULL);
view->details->view = CORBA_OBJECT_NIL;
+ nautilus_bonobo_object_call_when_remote_object_disappears
+ (view->details->view_frame, CORBA_OBJECT_NIL, NULL, NULL);
bonobo_object_unref (view->details->view_frame);
view->details->view_frame = NULL;
view->details->control_frame = NULL;
@@ -349,11 +344,6 @@ destroy_view (NautilusViewFrame *view)
}
bonobo_object_unref (BONOBO_OBJECT (view->details->ui_container));
view->details->ui_container = NULL;
-
- if (view->details->check_if_view_is_gone_timeout_id != 0) {
- g_source_remove (view->details->check_if_view_is_gone_timeout_id);
- view->details->check_if_view_is_gone_timeout_id = 0;
- }
}
static void
@@ -368,9 +358,13 @@ nautilus_view_frame_destroy (GtkObject *object)
nautilus_idle_queue_destroy (view->details->idle_queue);
- if (view->details->view_frame_failed_id != 0) {
- gtk_idle_remove (view->details->view_frame_failed_id);
- view->details->view_frame_failed_id = 0;
+ if (view->details->failed_idle_id != 0) {
+ gtk_idle_remove (view->details->failed_idle_id);
+ view->details->failed_idle_id = 0;
+ }
+ if (view->details->socket_gone_idle_id != 0) {
+ gtk_idle_remove (view->details->socket_gone_idle_id);
+ view->details->socket_gone_idle_id = 0;
}
/* It's good to be in "failed" state while shutting down
@@ -581,31 +575,6 @@ nautilus_view_frame_new (BonoboUIContainer *ui_container,
return view_frame;
}
-static gboolean
-check_if_view_is_gone (gpointer callback_data)
-{
- NautilusViewFrame *view;
- CORBA_Environment ev;
- gboolean view_is_gone;
-
- view = NAUTILUS_VIEW_FRAME (callback_data);
-
- CORBA_exception_init (&ev);
- view_is_gone = CORBA_Object_non_existent (view->details->view, &ev);
- if (ev._major != CORBA_NO_EXCEPTION) {
- view_is_gone = TRUE;
- }
- CORBA_exception_free (&ev);
-
- if (!view_is_gone) {
- return TRUE;
- }
-
- view->details->check_if_view_is_gone_timeout_id = 0;
- view_frame_failed (view);
- return FALSE;
-}
-
static void
emit_zoom_parameters_changed_callback (gpointer data,
gpointer callback_data)
@@ -701,16 +670,13 @@ create_corba_objects (NautilusViewFrame *view)
static gboolean
-view_frame_failed_callback (gpointer data)
+view_frame_failed_callback (gpointer callback_data)
{
- NautilusViewFrame *view = data;
-
- g_assert (NAUTILUS_IS_VIEW_FRAME (view));
-
- view->details->view_frame_failed_id = 0;
+ NautilusViewFrame *view;
+ view = NAUTILUS_VIEW_FRAME (callback_data);
+ view->details->failed_idle_id = 0;
view_frame_failed (view);
-
return FALSE;
}
@@ -719,12 +685,74 @@ queue_view_frame_failed (NautilusViewFrame *view)
{
g_assert (NAUTILUS_IS_VIEW_FRAME (view));
- if (view->details->view_frame_failed_id == 0)
- view->details->view_frame_failed_id =
+ if (view->details->failed_idle_id == 0)
+ view->details->failed_idle_id =
gtk_idle_add (view_frame_failed_callback, view);
}
static void
+view_frame_failed_cover (BonoboObject *object,
+ gpointer callback_data)
+{
+ view_frame_failed (NAUTILUS_VIEW_FRAME (callback_data));
+}
+
+static gboolean
+check_socket_gone_idle_callback (gpointer callback_data)
+{
+ NautilusViewFrame *frame;
+ GtkWidget *widget;
+ GList *children;
+
+ frame = NAUTILUS_VIEW_FRAME (callback_data);
+
+ frame->details->socket_gone_idle_id = 0;
+
+ widget = bonobo_control_frame_get_widget (frame->details->control_frame);
+
+ /* This relies on details of the BonoboControlFrame
+ * implementation, specifically that's there's one level of
+ * hierarchy between the widget returned by get_widget and the
+ * actual plug.
+ */
+ children = gtk_container_children (GTK_CONTAINER (widget));
+ g_list_free (children);
+
+ /* If there's nothing inside the widget at all, that means
+ * that the socket went away because the remote plug went away.
+ */
+ if (children == NULL) {
+ view_frame_failed (frame);
+ }
+
+ return FALSE;
+}
+
+static void
+check_socket_gone_callback (GtkContainer *container,
+ GtkWidget *widget,
+ gpointer callback_data)
+{
+ NautilusViewFrame *frame;
+
+ frame = NAUTILUS_VIEW_FRAME (callback_data);
+
+ /* There are two times the socket will be destroyed in Bonobo.
+ * One is when a local control decides to not use the socket.
+ * The other is when the remote plug goes away. The way to
+ * tell these apart is to wait until idle time. At idle time,
+ * if there's nothing in the container, then that means the
+ * real socket went away. If it was just the local control
+ * deciding not to use the socket, there will be another
+ * widget in there.
+ */
+ if (frame->details->socket_gone_idle_id == 0) {
+ frame->details->socket_gone_idle_id = gtk_idle_add
+ (check_socket_gone_idle_callback, callback_data);
+ }
+}
+
+static void
attach_view (NautilusViewFrame *view,
BonoboObjectClient *client)
{
@@ -745,6 +773,8 @@ attach_view (NautilusViewFrame *view,
create_corba_objects (view);
+ widget = bonobo_control_frame_get_widget (view->details->control_frame);
+
gtk_signal_connect_object_while_alive
(GTK_OBJECT (view->details->view_frame),
"destroy",
@@ -759,6 +789,12 @@ attach_view (NautilusViewFrame *view,
"system_exception",
queue_view_frame_failed, GTK_OBJECT (view));
+ gtk_signal_connect_while_alive
+ (GTK_OBJECT (widget),
+ "remove",
+ check_socket_gone_callback, view,
+ GTK_OBJECT (view));
+
if (view->details->zoomable_frame != NULL) {
gtk_signal_connect_object_while_alive
(GTK_OBJECT (view->details->zoomable_frame),
@@ -777,15 +813,16 @@ attach_view (NautilusViewFrame *view,
GTK_OBJECT (view));
}
- widget = bonobo_control_frame_get_widget (view->details->control_frame);
gtk_widget_show (widget);
gtk_container_add (GTK_CONTAINER (view), widget);
view_frame_activated (view);
- g_assert (view->details->check_if_view_is_gone_timeout_id == 0);
- view->details->check_if_view_is_gone_timeout_id
- = g_timeout_add (VIEW_RESPONSE_TIMEOUT, check_if_view_is_gone, view);
+ nautilus_bonobo_object_call_when_remote_object_disappears
+ (view->details->view_frame,
+ view->details->view,
+ view_frame_failed_cover,
+ view);
}
static void