diff options
Diffstat (limited to 'eel')
-rw-r--r-- | eel/eel-gtk-extensions.c | 553 | ||||
-rw-r--r-- | eel/eel-gtk-extensions.h | 38 | ||||
-rw-r--r-- | eel/eel-image-table.c | 168 |
3 files changed, 138 insertions, 621 deletions
diff --git a/eel/eel-gtk-extensions.c b/eel/eel-gtk-extensions.c index 94c4987d..7aab358e 100644 --- a/eel/eel-gtk-extensions.c +++ b/eel/eel-gtk-extensions.c @@ -430,30 +430,6 @@ eel_gtk_menu_insert_separator (GtkMenu *menu, int index) return GTK_MENU_ITEM (menu_item); } -void -eel_gtk_menu_set_item_visibility (GtkMenu *menu, int index, gboolean visible) -{ - GList *children; - GtkWidget *menu_item; - - g_return_if_fail (GTK_IS_MENU (menu)); - - children = gtk_container_get_children (GTK_CONTAINER (menu)); - g_return_if_fail (index >= 0 && index < (int) g_list_length (children)); - - menu_item = GTK_WIDGET (g_list_nth_data (children, index)); - if (visible) - { - gtk_widget_show (menu_item); - } - else - { - gtk_widget_hide (menu_item); - } - - g_list_free (children); -} - GtkWidget * eel_gtk_menu_tool_button_get_button (GtkMenuToolButton *tool_button) { @@ -474,37 +450,6 @@ eel_gtk_menu_tool_button_get_button (GtkMenuToolButton *tool_button) return button; } -gboolean -eel_point_in_allocation (const GtkAllocation *allocation, - int x, int y) -{ - g_return_val_if_fail (allocation != NULL, FALSE); - return x >= allocation->x - && y >= allocation->y - && x < allocation->x + allocation->width - && y < allocation->y + allocation->height; -} - -/* FIXME this function is dangerous, because gtk_widget_get_window (widget) coords (or - * other window-belonging-to-widget coords) do not need to be in the - * same coordinate system as widget->allocation. - * If you use this function, be aware of that. Someone should probably - * audit all uses, too. - */ -gboolean -eel_point_in_widget (GtkWidget *widget, - int x, int y) -{ - GtkAllocation allocation; - if (widget == NULL) - { - return FALSE; - } - g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); - gtk_widget_get_allocation (widget, &allocation); - return eel_point_in_allocation (&allocation, x, y); -} - /** * eel_gtk_widget_set_shown * @@ -603,167 +548,6 @@ eel_gtk_signal_connect_full_while_alive (GtkObject *object, info); } -typedef struct -{ - GtkObject *object; - guint object_destroy_handler; - - GtkWidget *realized_widget; - guint realized_widget_destroy_handler; - guint realized_widget_unrealized_handler; - - guint signal_handler; -} RealizeDisconnectInfo; - -static void -while_realized_disconnecter (GtkObject *object, - RealizeDisconnectInfo *info) -{ - g_assert (GTK_IS_OBJECT (object)); - g_assert (info != NULL); - g_assert (GTK_IS_OBJECT (info->object)); - g_assert (info->object_destroy_handler != 0); - g_assert (info->object_destroy_handler != 0); - g_assert (info->realized_widget_destroy_handler != 0); - g_assert (info->realized_widget_unrealized_handler != 0); - - g_signal_handler_disconnect (info->object, info->object_destroy_handler); - g_signal_handler_disconnect (info->object, info->signal_handler); - g_signal_handler_disconnect (info->realized_widget, info->realized_widget_destroy_handler); - g_signal_handler_disconnect (info->realized_widget, info->realized_widget_unrealized_handler); - g_free (info); -} - -/** - * eel_gtk_signal_connect_while_realized: - * - * @object: Object to connect to. - * @name: Name of signal to connect to. - * @callback: Caller's callback. - * @callback_data: Caller's callback_data. - * @realized_widget: Widget to monitor for realized state. Signal is connected - * while this wigget is realized. - * - * Connect to a signal of an object while another widget is realized. This is - * useful for non windowed widgets that need to monitor events in their ancestored - * windowed widget. The signal is automatically disconnected when &widget is - * unrealized. Also, the signal is automatically disconnected when either &object - * or &widget are destroyed. - **/ -void -eel_gtk_signal_connect_while_realized (GtkObject *object, - const char *name, - GCallback callback, - gpointer callback_data, - GtkWidget *realized_widget) -{ - RealizeDisconnectInfo *info; - - g_return_if_fail (GTK_IS_OBJECT (object)); - g_return_if_fail (name != NULL); - g_return_if_fail (name[0] != '\0'); - g_return_if_fail (callback != NULL); - g_return_if_fail (GTK_IS_WIDGET (realized_widget)); - g_return_if_fail (gtk_widget_get_realized (realized_widget)); - - info = g_new0 (RealizeDisconnectInfo, 1); - - info->object = object; - info->object_destroy_handler = - g_signal_connect (G_OBJECT (info->object), - "destroy", - G_CALLBACK (while_realized_disconnecter), - info); - - info->realized_widget = realized_widget; - info->realized_widget_destroy_handler = - g_signal_connect (G_OBJECT (info->realized_widget), - "destroy", - G_CALLBACK (while_realized_disconnecter), - info); - info->realized_widget_unrealized_handler = - g_signal_connect_after (G_OBJECT (info->realized_widget), - "unrealize", - G_CALLBACK (while_realized_disconnecter), - info); - - info->signal_handler = g_signal_connect (G_OBJECT (info->object), - name, callback, callback_data); -} - -/** - * eel_gtk_container_get_first_child. - * - * Returns the first child of a container. - * @container: The container. - **/ - -static void -get_first_callback (GtkWidget *widget, gpointer callback_data) -{ - GtkWidget **first_child_slot; - - g_assert (GTK_IS_WIDGET (widget)); - g_assert (callback_data != NULL); - - first_child_slot = callback_data; - - if (*first_child_slot == NULL) - { - *first_child_slot = widget; - /* We'd stop the iterating now if we could. */ - } - else - { - g_assert (GTK_IS_WIDGET (*first_child_slot)); - } -} - -GtkWidget * -eel_gtk_container_get_first_child (GtkContainer *container) -{ - GtkWidget *first_child; - - g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL); - - first_child = NULL; - gtk_container_foreach (container, get_first_callback, &first_child); - g_assert (first_child == NULL || GTK_IS_WIDGET (first_child)); - return first_child; -} - -typedef struct -{ - GtkCallback callback; - gpointer callback_data; -} container_foreach_deep_callback_data; - -static void -container_foreach_deep_callback (GtkWidget *child, gpointer data) -{ - container_foreach_deep_callback_data *deep_data; - - deep_data = (container_foreach_deep_callback_data *) data; - - deep_data->callback (child, deep_data->callback_data); - - if (GTK_IS_CONTAINER (child)) - { - gtk_container_foreach (GTK_CONTAINER (child), container_foreach_deep_callback, data); - } -} - -void -eel_gtk_container_foreach_deep (GtkContainer *container, - GtkCallback callback, - gpointer callback_data) -{ - container_foreach_deep_callback_data deep_data; - deep_data.callback = callback; - deep_data.callback_data = callback_data; - gtk_container_foreach (container, container_foreach_deep_callback, &deep_data); -} - /* The standard gtk_adjustment_set_value ignores page size, which * disagrees with the logic used by scroll bars, for example. */ @@ -822,172 +606,6 @@ eel_gtk_label_make_bold (GtkLabel *label) pango_font_description_free (font_desc); } -/** - * eel_gtk_label_set_scale: - * @label: - * @num_steps: - * - * Function is broken, see eel_gtk_label_make_larger() for explanation - * - **/ -void -eel_gtk_label_set_scale (GtkLabel *label, - double scale_factor) -{ - PangoAttrList *old_attr_list; - PangoAttrList *attr_list; - - g_return_if_fail (GTK_IS_LABEL (label)); - g_return_if_fail (scale_factor > 0); - - old_attr_list = gtk_label_get_attributes (label); - attr_list = eel_pango_attr_list_apply_global_attribute (old_attr_list, - pango_attr_scale_new (scale_factor)); - gtk_label_set_attributes (label, attr_list); - pango_attr_list_unref (attr_list); -} - -static void -get_layout_location (GtkLabel *label, - gint *xp, - gint *yp) -{ - GtkMisc *misc; - GtkWidget *widget; - float xalign, yalign; - int x, y, xpad, ypad; - int shadow_offset; - GtkAllocation allocation; - GtkRequisition req; - - shadow_offset = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), - "eel-label-shadow-offset")); - - misc = GTK_MISC (label); - widget = GTK_WIDGET (label); - gtk_misc_get_alignment (misc, &xalign, &yalign); - gtk_misc_get_padding (misc, &xpad, &ypad); - - if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR) - xalign = 1.0 - xalign; - - gtk_widget_get_allocation (widget, &allocation); - gtk_widget_get_requisition (widget, &req); - x = floor (allocation.x + xpad - + ((allocation.width - req.width - shadow_offset) * xalign) - + 0.5); - - y = floor (allocation.y + ypad - + ((allocation.height - req.height - shadow_offset) * yalign) - + 0.5); - - - if (xp) - *xp = x; - - if (yp) - *yp = y; -} - -static gboolean -eel_gtk_label_expose_event (GtkLabel *label, GdkEventExpose *event, gpointer user_data) -{ - int x, y; - GdkColor color; - GtkWidget *widget; - GdkGC *gc; - guint32 shadow_color; - int shadow_offset; - - shadow_color = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), - "eel-label-shadow-color")); - shadow_offset = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), - "eel-label-shadow-offset")); - - color = eel_gdk_rgb_to_color (shadow_color); - - get_layout_location (label, &x, &y); - - widget = GTK_WIDGET (label); - if (shadow_offset > 0) - { - gc = gdk_gc_new (gtk_widget_get_window (widget)); - gdk_gc_set_rgb_fg_color (gc, &color); - gdk_gc_set_clip_rectangle (gc, &event->area); - - gdk_draw_layout (gtk_widget_get_window (widget), - gc, - x + shadow_offset, y + shadow_offset, - gtk_label_get_layout (label)); - g_object_unref (gc); - } - - gtk_paint_layout (gtk_widget_get_style (widget), - gtk_widget_get_window (widget), - gtk_widget_get_state (widget), - FALSE, - &event->area, - widget, - "label", - x, y, - gtk_label_get_layout (label)); - - return TRUE; -} - -static void -eel_gtk_label_size_request (GtkLabel *label, GtkRequisition *requisition, gpointer user_data) -{ - gint shadow_offset; - - shadow_offset = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (label), - "eel-label-shadow-offset")); - - requisition->width += shadow_offset; - requisition->height += shadow_offset; -} - -static void -set_up_label (GtkLabel *label) -{ - - if (g_object_get_data (G_OBJECT (label), "eel-label-set-up") != NULL) - { - return; - } - - g_signal_connect (label, "expose_event", - G_CALLBACK (eel_gtk_label_expose_event), NULL); - g_signal_connect_after (label, "size_request", - G_CALLBACK (eel_gtk_label_size_request), NULL); - - g_object_set_data (G_OBJECT (label), "eel-label-set-up", "eel-label-set-up"); -} - -void -eel_gtk_label_set_drop_shadow_color (GtkLabel *label, - guint32 color) -{ - set_up_label (label); - - g_object_set_data (G_OBJECT (label), "eel-label-shadow-color", - GINT_TO_POINTER (color)); - - gtk_widget_queue_draw (GTK_WIDGET (label)); -} - -void -eel_gtk_label_set_drop_shadow_offset (GtkLabel *label, - gint offset) -{ - set_up_label (label); - - g_object_set_data (G_OBJECT (label), "eel-label-shadow-offset", - GINT_TO_POINTER (offset)); - - gtk_widget_queue_draw (GTK_WIDGET (label)); -} - void eel_gtk_widget_set_background_color (GtkWidget *widget, const char *color_spec) @@ -1020,78 +638,6 @@ eel_gtk_widget_set_foreground_color (GtkWidget *widget, gtk_widget_modify_text (widget, GTK_STATE_ACTIVE, &color); } -GtkWidget * -eel_gtk_widget_find_windowed_ancestor (GtkWidget *widget) -{ - g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - - while (widget && !gtk_widget_get_has_window (widget)) - { - widget = gtk_widget_get_parent (widget); - } - - return widget; -} - -/* eel_gtk_get_system_font: - * - * Return the system font as selected in the control center. Need to - * g_object_unref() the result when done with it. - * - * Perhaps there is a better way to figure out what that font is, but - * the following is simple enough and it works. - */ -PangoFontDescription * -eel_gtk_get_system_font (void) -{ - GtkWidget *label; - PangoFontDescription *font; - - label = gtk_label_new (""); - - gtk_widget_ensure_style (label); - - font = pango_font_description_copy (gtk_widget_get_style (label)->font_desc); - - g_object_ref_sink (label); - g_object_unref (label); - - return font; -} - -void -eel_gtk_widget_get_button_event_location (GtkWidget *widget, - const GdkEventButton *event, - int *x, - int *y) -{ - int window_x, window_y; - GtkAllocation allocation; - - g_return_if_fail (GTK_IS_WIDGET (widget)); - g_return_if_fail (event != NULL); - - gdk_window_get_position (event->window, &window_x, &window_y); - gtk_widget_get_allocation (widget, &allocation); - if (x != NULL) - { - *x = event->x + window_x - allocation.x; - } - if (y != NULL) - { - *y = event->y + window_y - allocation.y; - } -} - -void -eel_gtk_widget_get_motion_event_location (GtkWidget *widget, - const GdkEventMotion *event, - int *x, - int *y) -{ - eel_gtk_widget_get_button_event_location (widget, (const GdkEventButton *) event, x, y); -} - static gboolean tree_view_button_press_callback (GtkWidget *tree_view, GdkEventButton *event, @@ -1146,102 +692,3 @@ eel_gtk_tree_view_set_activate_on_single_click (GtkTreeView *tree_view, GUINT_TO_POINTER (button_press_id)); } } - -gboolean -eel_gtk_viewport_get_visible_rect (GtkViewport *viewport, - GdkRectangle *rect) -{ - GdkRectangle viewport_rect; - GdkRectangle child_rect; - gboolean return_val; - - g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), FALSE); - g_return_val_if_fail (rect != NULL, FALSE); - - if (gtk_widget_get_realized (GTK_WIDGET (viewport))) - { - viewport_rect.x = 0; - viewport_rect.y = 0; - -#if GTK_CHECK_VERSION(3, 0, 0) - viewport_rect.width = gdk_window_get_width(GDK_WINDOW(gtk_viewport_get_view_window(viewport))); - viewport_rect.height = gdk_window_get_height(GDK_WINDOW(gtk_viewport_get_view_window(viewport))); -#else - gdk_drawable_get_size(gtk_viewport_get_view_window(viewport), &viewport_rect.width, &viewport_rect.height); -#endif - - gdk_window_get_position (gtk_viewport_get_bin_window (viewport), - &child_rect.x, - &child_rect.y); - -#if GTK_CHECK_VERSION(3, 0, 0) - child_rect.width = gdk_window_get_width(GDK_WINDOW(gtk_viewport_get_view_window(viewport))); - child_rect.height = gdk_window_get_height(GDK_WINDOW(gtk_viewport_get_view_window(viewport))); -#else - gdk_drawable_get_size(gtk_viewport_get_bin_window(viewport), &child_rect.width, &child_rect.height); -#endif - - return_val = gdk_rectangle_intersect (&viewport_rect, - &child_rect, - rect); - rect->x -= child_rect.x; - rect->y -= child_rect.y; - - return return_val; - } - - rect->x = rect->y = rect->width = rect->height = 0; - return FALSE; -} - -void -eel_gtk_viewport_scroll_to_rect (GtkViewport *viewport, - GdkRectangle *rect) -{ - GdkRectangle visible_rect; - int scroll_x; - int scroll_y; - GtkAdjustment *adjustment; - - g_return_if_fail (GTK_IS_VIEWPORT (viewport)); - g_return_if_fail (rect != NULL); - - if (eel_gtk_viewport_get_visible_rect (viewport, &visible_rect)) - { - scroll_x = -1; - scroll_y = -1; - - if (rect->x + rect->width > visible_rect.x + visible_rect.width) - { - scroll_x = rect->x - (visible_rect.width - rect->width); - } - if (rect->y + rect->height > visible_rect.y + visible_rect.height) - { - scroll_y = rect->y - (visible_rect.height - rect->height); - } - - if (rect->x < visible_rect.x) - { - scroll_x = rect->x; - } - - if (rect->y < visible_rect.y) - { - scroll_y = rect->y; - } - - adjustment = gtk_viewport_get_hadjustment (viewport); - if (adjustment && scroll_x != -1) - { - eel_gtk_adjustment_set_value (adjustment, - (double)scroll_x); - } - - adjustment = gtk_viewport_get_vadjustment (viewport); - if (adjustment && scroll_y != -1) - { - eel_gtk_adjustment_set_value (adjustment, - (double)scroll_y); - } - } -} diff --git a/eel/eel-gtk-extensions.h b/eel/eel-gtk-extensions.h index e286bf74..1da3e8f4 100644 --- a/eel/eel-gtk-extensions.h +++ b/eel/eel-gtk-extensions.h @@ -54,32 +54,10 @@ void eel_gtk_signal_connect_while_realized (GtkObject /* GtkWidget */ void eel_gtk_widget_set_shown (GtkWidget *widget, gboolean shown); -gboolean eel_point_in_allocation (const GtkAllocation *allocation, - int x, - int y); -gboolean eel_point_in_widget (GtkWidget *widget, - int x, - int y); void eel_gtk_widget_set_background_color (GtkWidget *widget, const char *color_spec); void eel_gtk_widget_set_foreground_color (GtkWidget *widget, const char *color_spec); -GtkWidget * eel_gtk_widget_find_windowed_ancestor (GtkWidget *widget); -PangoFontDescription *eel_gtk_get_system_font (void); -void eel_gtk_widget_get_button_event_location (GtkWidget *widget, - const GdkEventButton *event, - int *x, - int *y); -void eel_gtk_widget_get_motion_event_location (GtkWidget *widget, - const GdkEventMotion *event, - int *x, - int *y); - -/* GtkContainer */ -GtkWidget * eel_gtk_container_get_first_child (GtkContainer *container); -void eel_gtk_container_foreach_deep (GtkContainer *container, - GtkCallback callback, - gpointer callback_data); /* GtkWindow */ void eel_gtk_window_set_initial_geometry (GtkWindow *window, @@ -107,21 +85,12 @@ void eel_pop_up_context_menu (GtkMenu GtkMenuItem * eel_gtk_menu_append_separator (GtkMenu *menu); GtkMenuItem * eel_gtk_menu_insert_separator (GtkMenu *menu, int index); -void eel_gtk_menu_set_item_visibility (GtkMenu *menu, - int index, - gboolean visible); /* GtkMenuToolButton */ GtkWidget * eel_gtk_menu_tool_button_get_button (GtkMenuToolButton *tool_button); /* GtkLabel */ void eel_gtk_label_make_bold (GtkLabel *label); -void eel_gtk_label_set_scale (GtkLabel *label, - double scale_factor); -void eel_gtk_label_set_drop_shadow_color (GtkLabel *label, - guint32 color); -void eel_gtk_label_set_drop_shadow_offset (GtkLabel *label, - gint offset); /* GtkAdjustment */ void eel_gtk_adjustment_set_value (GtkAdjustment *adjustment, float value); @@ -131,11 +100,4 @@ void eel_gtk_adjustment_clamp_value (GtkAdjust void eel_gtk_tree_view_set_activate_on_single_click (GtkTreeView *tree_view, gboolean should_activate); -/* GtkViewport */ -gboolean eel_gtk_viewport_get_visible_rect (GtkViewport *viewport, - GdkRectangle *rect); - -void eel_gtk_viewport_scroll_to_rect (GtkViewport *viewport, - GdkRectangle *rect); - #endif /* EEL_GTK_EXTENSIONS_H */ diff --git a/eel/eel-image-table.c b/eel/eel-image-table.c index 8f87660b..54b3947d 100644 --- a/eel/eel-image-table.c +++ b/eel/eel-image-table.c @@ -88,6 +88,13 @@ static void image_table_emit_signal (EelImageTable *image_t guint state, GdkEvent *event); +/* Ancestor methods */ +GtkWidget * find_windowed_ancestor (GtkWidget *widget); +static void signal_connect_while_realized (GtkObject *object, + const char *name, + GCallback callback, + gpointer callback_data, + GtkWidget *realized_widget); /* Ancestor callbacks */ static int ancestor_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, @@ -209,7 +216,7 @@ eel_image_table_realize (GtkWidget *widget) /* Chain realize */ EEL_CALL_PARENT (GTK_WIDGET_CLASS, realize, (widget)); - windowed_ancestor = eel_gtk_widget_find_windowed_ancestor (widget); + windowed_ancestor = find_windowed_ancestor (widget); g_assert (GTK_IS_WIDGET (windowed_ancestor)); gtk_widget_add_events (windowed_ancestor, @@ -220,35 +227,35 @@ eel_image_table_realize (GtkWidget *widget) | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), - "enter_notify_event", - G_CALLBACK (ancestor_enter_notify_event), - widget, - widget); - - eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), - "leave_notify_event", - G_CALLBACK (ancestor_leave_notify_event), - widget, - widget); - - eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), - "motion_notify_event", - G_CALLBACK (ancestor_motion_notify_event), - widget, - widget); - - eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), - "button_press_event", - G_CALLBACK (ancestor_button_press_event), - widget, - widget); - - eel_gtk_signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), - "button_release_event", - G_CALLBACK (ancestor_button_release_event), - widget, - widget); + signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), + "enter_notify_event", + G_CALLBACK (ancestor_enter_notify_event), + widget, + widget); + + signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), + "leave_notify_event", + G_CALLBACK (ancestor_leave_notify_event), + widget, + widget); + + signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), + "motion_notify_event", + G_CALLBACK (ancestor_motion_notify_event), + widget, + widget); + + signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), + "button_press_event", + G_CALLBACK (ancestor_button_press_event), + widget, + widget); + + signal_connect_while_realized (GTK_OBJECT (windowed_ancestor), + "button_release_event", + G_CALLBACK (ancestor_button_release_event), + widget, + widget); } static void @@ -401,6 +408,107 @@ image_table_handle_motion (EelImageTable *image_table, } } +GtkWidget * +find_windowed_ancestor (GtkWidget *widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); + + while (widget && !gtk_widget_get_has_window (widget)) + { + widget = gtk_widget_get_parent (widget); + } + + return widget; +} + +typedef struct +{ + GtkObject *object; + guint object_destroy_handler; + + GtkWidget *realized_widget; + guint realized_widget_destroy_handler; + guint realized_widget_unrealized_handler; + + guint signal_handler; +} RealizeDisconnectInfo; + +static void +while_realized_disconnecter (GtkObject *object, + RealizeDisconnectInfo *info) +{ + g_assert (GTK_IS_OBJECT (object)); + g_assert (info != NULL); + g_assert (GTK_IS_OBJECT (info->object)); + g_assert (info->object_destroy_handler != 0); + g_assert (info->object_destroy_handler != 0); + g_assert (info->realized_widget_destroy_handler != 0); + g_assert (info->realized_widget_unrealized_handler != 0); + + g_signal_handler_disconnect (info->object, info->object_destroy_handler); + g_signal_handler_disconnect (info->object, info->signal_handler); + g_signal_handler_disconnect (info->realized_widget, info->realized_widget_destroy_handler); + g_signal_handler_disconnect (info->realized_widget, info->realized_widget_unrealized_handler); + g_free (info); +} + +/** + * signal_connect_while_realized: + * + * @object: Object to connect to. + * @name: Name of signal to connect to. + * @callback: Caller's callback. + * @callback_data: Caller's callback_data. + * @realized_widget: Widget to monitor for realized state. Signal is connected + * while this wigget is realized. + * + * Connect to a signal of an object while another widget is realized. This is + * useful for non windowed widgets that need to monitor events in their ancestored + * windowed widget. The signal is automatically disconnected when &widget is + * unrealized. Also, the signal is automatically disconnected when either &object + * or &widget are destroyed. + **/ +static void +signal_connect_while_realized (GtkObject *object, + const char *name, + GCallback callback, + gpointer callback_data, + GtkWidget *realized_widget) +{ + RealizeDisconnectInfo *info; + + g_return_if_fail (GTK_IS_OBJECT (object)); + g_return_if_fail (name != NULL); + g_return_if_fail (name[0] != '\0'); + g_return_if_fail (callback != NULL); + g_return_if_fail (GTK_IS_WIDGET (realized_widget)); + g_return_if_fail (gtk_widget_get_realized (realized_widget)); + + info = g_new0 (RealizeDisconnectInfo, 1); + + info->object = object; + info->object_destroy_handler = + g_signal_connect (G_OBJECT (info->object), + "destroy", + G_CALLBACK (while_realized_disconnecter), + info); + + info->realized_widget = realized_widget; + info->realized_widget_destroy_handler = + g_signal_connect (G_OBJECT (info->realized_widget), + "destroy", + G_CALLBACK (while_realized_disconnecter), + info); + info->realized_widget_unrealized_handler = + g_signal_connect_after (G_OBJECT (info->realized_widget), + "unrealize", + G_CALLBACK (while_realized_disconnecter), + info); + + info->signal_handler = g_signal_connect (G_OBJECT (info->object), + name, callback, callback_data); +} + static int ancestor_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event, |